diff options
862 files changed, 12409 insertions, 6136 deletions
diff --git a/Android.bp b/Android.bp index 2321cc5dd61d..71023bf647c8 100644 --- a/Android.bp +++ b/Android.bp @@ -581,4 +581,5 @@ build = [ "StubLibraries.bp", "ApiDocs.bp", "ProtoLibraries.bp", + "TestProtoLibraries.bp", ] diff --git a/TestProtoLibraries.bp b/TestProtoLibraries.bp new file mode 100644 index 000000000000..8e269d0a85c5 --- /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/Android.bp b/apex/appsearch/Android.bp index 9a420160d3fd..827842633942 100644 --- a/apex/appsearch/Android.bp +++ b/apex/appsearch/Android.bp @@ -29,6 +29,7 @@ apex { key: "com.android.appsearch.key", certificate: ":com.android.appsearch.certificate", updatable: false, + generate_hashtree: false, } apex_key { 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 6e81afcdc912..d5271a6cb92e 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 @@ import java.util.concurrent.Executor; * @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 @@ public final class AppSearchConfig implements AutoCloseable { 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 @@ public final class AppSearchConfig implements AutoCloseable { 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 0709ff5fc48c..e5244296b1f4 100644 --- a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java +++ b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java @@ -179,7 +179,7 @@ public class AppSearchManagerService extends SystemService { */ 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) { @@ -224,7 +224,7 @@ public class AppSearchManagerService extends SystemService { 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. @@ -348,19 +348,19 @@ public class AppSearchManagerService extends SystemService { 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis); int totalLatencyMillis = (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis); - CallStats.Builder cBuilder = new CallStats.Builder(packageName, - databaseName) + logger.logStats(new CallStats.Builder() + .setPackageName(packageName) + .setDatabase(databaseName) + .setStatusCode(statusCode) + .setTotalLatencyMillis(totalLatencyMillis) .setCallType(CallStats.CALL_TYPE_SET_SCHEMA) // TODO(b/173532925) check the existing binder call latency chart // is good enough for us: // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis) .setNumOperationsSucceeded(operationSuccessCount) - .setNumOperationsFailed(operationFailureCount); - cBuilder.getGeneralStatsBuilder() - .setStatusCode(statusCode) - .setTotalLatencyMillis(totalLatencyMillis); - logger.logStats(cBuilder.build()); + .setNumOperationsFailed(operationFailureCount) + .build()); } } }); @@ -480,19 +480,19 @@ public class AppSearchManagerService extends SystemService { 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis); int totalLatencyMillis = (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis); - CallStats.Builder cBuilder = new CallStats.Builder(packageName, - databaseName) + logger.logStats(new CallStats.Builder() + .setPackageName(packageName) + .setDatabase(databaseName) + .setStatusCode(statusCode) + .setTotalLatencyMillis(totalLatencyMillis) .setCallType(CallStats.CALL_TYPE_PUT_DOCUMENTS) // TODO(b/173532925) check the existing binder call latency chart // is good enough for us: // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis) .setNumOperationsSucceeded(operationSuccessCount) - .setNumOperationsFailed(operationFailureCount); - cBuilder.getGeneralStatsBuilder() - .setStatusCode(statusCode) - .setTotalLatencyMillis(totalLatencyMillis); - logger.logStats(cBuilder.build()); + .setNumOperationsFailed(operationFailureCount) + .build()); } } }); @@ -563,19 +563,19 @@ public class AppSearchManagerService extends SystemService { 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis); int totalLatencyMillis = (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis); - CallStats.Builder cBuilder = new CallStats.Builder(packageName, - databaseName) + logger.logStats(new CallStats.Builder() + .setPackageName(packageName) + .setDatabase(databaseName) + .setStatusCode(statusCode) + .setTotalLatencyMillis(totalLatencyMillis) .setCallType(CallStats.CALL_TYPE_GET_DOCUMENTS) // TODO(b/173532925) check the existing binder call latency chart // is good enough for us: // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis) .setNumOperationsSucceeded(operationSuccessCount) - .setNumOperationsFailed(operationFailureCount); - cBuilder.getGeneralStatsBuilder() - .setStatusCode(statusCode) - .setTotalLatencyMillis(totalLatencyMillis); - logger.logStats(cBuilder.build()); + .setNumOperationsFailed(operationFailureCount) + .build()); } } }); @@ -631,19 +631,19 @@ public class AppSearchManagerService extends SystemService { 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis); int totalLatencyMillis = (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis); - CallStats.Builder cBuilder = new CallStats.Builder(packageName, - databaseName) + logger.logStats(new CallStats.Builder() + .setPackageName(packageName) + .setDatabase(databaseName) + .setStatusCode(statusCode) + .setTotalLatencyMillis(totalLatencyMillis) .setCallType(CallStats.CALL_TYPE_SEARCH) // TODO(b/173532925) check the existing binder call latency chart // is good enough for us: // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis) .setNumOperationsSucceeded(operationSuccessCount) - .setNumOperationsFailed(operationFailureCount); - cBuilder.getGeneralStatsBuilder() - .setStatusCode(statusCode) - .setTotalLatencyMillis(totalLatencyMillis); - logger.logStats(cBuilder.build()); + .setNumOperationsFailed(operationFailureCount) + .build()); } } }); @@ -697,20 +697,18 @@ public class AppSearchManagerService extends SystemService { 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis); int totalLatencyMillis = (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis); - // TODO(b/173532925) database would be nulluable once we remove generalStats - CallStats.Builder cBuilder = new CallStats.Builder(packageName, - /*database=*/ "") + logger.logStats(new CallStats.Builder() + .setPackageName(packageName) + .setStatusCode(statusCode) + .setTotalLatencyMillis(totalLatencyMillis) .setCallType(CallStats.CALL_TYPE_GLOBAL_SEARCH) // TODO(b/173532925) check the existing binder call latency chart // is good enough for us: // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis) .setNumOperationsSucceeded(operationSuccessCount) - .setNumOperationsFailed(operationFailureCount); - cBuilder.getGeneralStatsBuilder() - .setStatusCode(statusCode) - .setTotalLatencyMillis(totalLatencyMillis); - logger.logStats(cBuilder.build()); + .setNumOperationsFailed(operationFailureCount) + .build()); } } }); @@ -965,19 +963,19 @@ public class AppSearchManagerService extends SystemService { 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis); int totalLatencyMillis = (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis); - CallStats.Builder cBuilder = new CallStats.Builder(packageName, - databaseName) + logger.logStats(new CallStats.Builder() + .setPackageName(packageName) + .setDatabase(databaseName) + .setStatusCode(statusCode) + .setTotalLatencyMillis(totalLatencyMillis) .setCallType(CallStats.CALL_TYPE_REMOVE_DOCUMENTS_BY_ID) // TODO(b/173532925) check the existing binder call latency chart // is good enough for us: // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis) .setNumOperationsSucceeded(operationSuccessCount) - .setNumOperationsFailed(operationFailureCount); - cBuilder.getGeneralStatsBuilder() - .setStatusCode(statusCode) - .setTotalLatencyMillis(totalLatencyMillis); - logger.logStats(cBuilder.build()); + .setNumOperationsFailed(operationFailureCount) + .build()); } } }); @@ -1033,19 +1031,19 @@ public class AppSearchManagerService extends SystemService { 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis); int totalLatencyMillis = (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis); - CallStats.Builder cBuilder = new CallStats.Builder(packageName, - databaseName) + logger.logStats(new CallStats.Builder() + .setPackageName(packageName) + .setDatabase(databaseName) + .setStatusCode(statusCode) + .setTotalLatencyMillis(totalLatencyMillis) .setCallType(CallStats.CALL_TYPE_REMOVE_DOCUMENTS_BY_SEARCH) // TODO(b/173532925) check the existing binder call latency chart // is good enough for us: // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis) .setNumOperationsSucceeded(operationSuccessCount) - .setNumOperationsFailed(operationFailureCount); - cBuilder.getGeneralStatsBuilder() - .setStatusCode(statusCode) - .setTotalLatencyMillis(totalLatencyMillis); - logger.logStats(cBuilder.build()); + .setNumOperationsFailed(operationFailureCount) + .build()); } } }); @@ -1110,19 +1108,17 @@ public class AppSearchManagerService extends SystemService { 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis); int totalLatencyMillis = (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis); - CallStats.Builder cBuilder = new CallStats.Builder(/*packageName=*/ "", - /*databaseName=*/ "") + logger.logStats(new CallStats.Builder() + .setStatusCode(statusCode) + .setTotalLatencyMillis(totalLatencyMillis) .setCallType(CallStats.CALL_TYPE_FLUSH) // TODO(b/173532925) check the existing binder call latency chart // is good enough for us: // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis) .setNumOperationsSucceeded(operationSuccessCount) - .setNumOperationsFailed(operationFailureCount); - cBuilder.getGeneralStatsBuilder() - .setStatusCode(statusCode) - .setTotalLatencyMillis(totalLatencyMillis); - logger.logStats(cBuilder.build()); + .setNumOperationsFailed(operationFailureCount) + .build()); } } }); @@ -1147,7 +1143,8 @@ public class AppSearchManagerService extends SystemService { try { verifyUserUnlocked(callingUser); logger = mLoggerInstanceManager.getOrCreatePlatformLogger( - mContext, callingUser); + mContext, callingUser, + AppSearchConfig.getInstance(EXECUTOR)); mImplInstanceManager.getOrCreateAppSearchImpl(mContext, callingUser, logger); ++operationSuccessCount; invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null)); @@ -1161,21 +1158,17 @@ public class AppSearchManagerService extends SystemService { 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis); int totalLatencyMillis = (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis); - // TODO(b/173532925) make packageName and database nullable after - // removing generalStats - CallStats.Builder cBuilder = new CallStats.Builder(/*packageName=*/"", - /*database=*/ "") + logger.logStats(new CallStats.Builder() + .setStatusCode(statusCode) + .setTotalLatencyMillis(totalLatencyMillis) .setCallType(CallStats.CALL_TYPE_INITIALIZE) // TODO(b/173532925) check the existing binder call latency chart // is good enough for us: // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis) .setNumOperationsSucceeded(operationSuccessCount) - .setNumOperationsFailed(operationFailureCount); - cBuilder.getGeneralStatsBuilder() - .setStatusCode(statusCode) - .setTotalLatencyMillis(totalLatencyMillis); - logger.logStats(cBuilder.build()); + .setNumOperationsFailed(operationFailureCount) + .build()); } } }); @@ -1313,7 +1306,8 @@ public class AppSearchManagerService extends SystemService { 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(); @@ -1341,7 +1335,8 @@ public class AppSearchManagerService extends SystemService { 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++) { @@ -1370,7 +1365,8 @@ public class AppSearchManagerService extends SystemService { 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 077527220149..2181dab90681 100644 --- a/apex/appsearch/service/java/com/android/server/appsearch/ImplInstanceManager.java +++ b/apex/appsearch/service/java/com/android/server/appsearch/ImplInstanceManager.java @@ -24,10 +24,12 @@ import android.content.Context; import android.os.Environment; import android.os.UserHandle; import android.util.ArrayMap; +import android.util.Log; import com.android.internal.annotations.GuardedBy; import com.android.server.appsearch.external.localstorage.AppSearchImpl; import com.android.server.appsearch.external.localstorage.AppSearchLogger; +import com.android.server.appsearch.external.localstorage.FrameworkOptimizeStrategy; import java.io.File; import java.util.Map; @@ -37,9 +39,10 @@ import java.util.Objects; * Manages the lifecycle of instances of {@link AppSearchImpl}. * * <p>These instances are managed per unique device-user. + * @hide */ public final class ImplInstanceManager { - private static final String APP_SEARCH_DIR = "appSearch"; + private static final String TAG = "AppSearchImplInstanceMa"; private static ImplInstanceManager sImplInstanceManager; @@ -70,8 +73,11 @@ public final class ImplInstanceManager { * <p>This folder should only be accessed after unlock. */ public static File getAppSearchDir(@NonNull UserHandle userHandle) { - return new File( - Environment.getDataSystemCeDirectory(userHandle.getIdentifier()), APP_SEARCH_DIR); + // Duplicates the implementation of Environment#getDataSystemCeDirectory + // TODO(b/191059409): Unhide Environment#getDataSystemCeDirectory and switch to it. + File systemCeDir = new File(Environment.getDataDirectory(), "system_ce"); + File systemCeUserDir = new File(systemCeDir, String.valueOf(userHandle.getIdentifier())); + return new File(systemCeUserDir, "appSearch"); } /** @@ -104,25 +110,6 @@ public final class ImplInstanceManager { } /** - * 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,6 +159,12 @@ public final class ImplInstanceManager { @Nullable AppSearchLogger logger) throws AppSearchException { File appSearchDir = getAppSearchDir(userHandle); - return AppSearchImpl.create(appSearchDir, userContext, /*logger=*/ null); + File icingDir = new File(appSearchDir, "icing"); + Log.i(TAG, "Creating new AppSearch instance at: " + icingDir); + return AppSearchImpl.create( + icingDir, + userContext, + /*logger=*/ null, + new FrameworkOptimizeStrategy()); } } diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java index 29cb57c05eeb..4a1a9ae3546b 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 @@ -145,14 +145,14 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; public final class AppSearchImpl implements Closeable { private static final String TAG = "AppSearchImpl"; - @VisibleForTesting static final int OPTIMIZE_THRESHOLD_DOC_COUNT = 1000; - @VisibleForTesting static final int OPTIMIZE_THRESHOLD_BYTES = 1_000_000; // 1MB @VisibleForTesting static final int CHECK_OPTIMIZE_INTERVAL = 100; private final ReadWriteLock mReadWriteLock = new ReentrantReadWriteLock(); private final LogUtil mLogUtil = new LogUtil(TAG); + private final OptimizeStrategy mOptimizeStrategy; + @GuardedBy("mReadWriteLock") @VisibleForTesting final IcingSearchEngine mIcingSearchEngineLocked; @@ -201,10 +201,12 @@ public final class AppSearchImpl implements Closeable { public static AppSearchImpl create( @NonNull File icingDir, @NonNull Context userContext, - @Nullable AppSearchLogger logger) + @Nullable AppSearchLogger logger, + @NonNull OptimizeStrategy optimizeStrategy) throws AppSearchException { Objects.requireNonNull(icingDir); Objects.requireNonNull(userContext); + Objects.requireNonNull(optimizeStrategy); long totalLatencyStartMillis = SystemClock.elapsedRealtime(); InitializeStats.Builder initStatsBuilder = null; @@ -212,7 +214,9 @@ public final class AppSearchImpl implements Closeable { initStatsBuilder = new InitializeStats.Builder(); } - AppSearchImpl appSearchImpl = new AppSearchImpl(icingDir, userContext, initStatsBuilder); + AppSearchImpl appSearchImpl = + new AppSearchImpl( + icingDir, userContext, initStatsBuilder, optimizeStrategy); long prepareVisibilityStoreLatencyStartMillis = SystemClock.elapsedRealtime(); appSearchImpl.initializeVisibilityStore(); @@ -236,7 +240,8 @@ public final class AppSearchImpl implements Closeable { private AppSearchImpl( @NonNull File icingDir, @NonNull Context userContext, - @Nullable InitializeStats.Builder initStatsBuilder) + @Nullable InitializeStats.Builder initStatsBuilder, + @NonNull OptimizeStrategy optimizeStrategy) throws AppSearchException { mReadWriteLock.writeLock().lock(); @@ -254,6 +259,7 @@ public final class AppSearchImpl implements Closeable { Objects.hashCode(mIcingSearchEngineLocked)); mVisibilityStoreLocked = new VisibilityStore(this, userContext); + mOptimizeStrategy = optimizeStrategy; // The core initialization procedure. If any part of this fails, we bail into // resetLocked(), deleting all data (but hopefully allowing AppSearchImpl to come up). @@ -646,9 +652,7 @@ public final class AppSearchImpl implements Closeable { // Logging stats if (pStatsBuilder != null) { pStatsBuilder - .getGeneralStatsBuilder() - .setStatusCode(statusProtoToResultCode(putResultProto.getStatus())); - pStatsBuilder + .setStatusCode(statusProtoToResultCode(putResultProto.getStatus())) .setGenerateDocumentProtoLatencyMillis( (int) (generateDocumentProtoEndTimeMillis @@ -667,9 +671,8 @@ public final class AppSearchImpl implements Closeable { if (logger != null) { long totalEndTimeMillis = SystemClock.elapsedRealtime(); - pStatsBuilder - .getGeneralStatsBuilder() - .setTotalLatencyMillis((int) (totalEndTimeMillis - totalStartTimeMillis)); + pStatsBuilder.setTotalLatencyMillis( + (int) (totalEndTimeMillis - totalStartTimeMillis)); logger.logStats(pStatsBuilder.build()); } } @@ -812,7 +815,8 @@ public final class AppSearchImpl implements Closeable { * * @param queryExpression Query String to search. * @param searchSpec Spec for setting filters, raw query etc. - * @param callerPackageName Package name of the caller, should belong to the {@code callerUid}. + * @param callerPackageName Package name of the caller, should belong to the {@code + * userContext}. * @param callerUid UID of the client making the globalQuery call. * @param logger logger to collect globalQuery stats * @return The results of performing this search. It may contain an empty list of results if no @@ -2001,7 +2005,7 @@ public final class AppSearchImpl implements Closeable { * resources that could be released. * * <p>{@link IcingSearchEngine#optimize()} should be called only if {@link - * GetOptimizeInfoResultProto} shows there is enough resources could be released. + * OptimizeStrategy#shouldOptimize(GetOptimizeInfoResultProto)} return true. */ public void checkForOptimize() throws AppSearchException { mReadWriteLock.writeLock().lock(); @@ -2009,9 +2013,7 @@ public final class AppSearchImpl implements Closeable { GetOptimizeInfoResultProto optimizeInfo = getOptimizeInfoResultLocked(); checkSuccess(optimizeInfo.getStatus()); mOptimizeIntervalCountLocked = 0; - // Second threshold, decide when to call optimize(). - if (optimizeInfo.getOptimizableDocs() >= OPTIMIZE_THRESHOLD_DOC_COUNT - || optimizeInfo.getEstimatedOptimizableBytes() >= OPTIMIZE_THRESHOLD_BYTES) { + if (mOptimizeStrategy.shouldOptimize(optimizeInfo)) { optimize(); } } finally { @@ -2022,11 +2024,7 @@ public final class AppSearchImpl implements Closeable { // go/icing-library-apis. } - /** - * Triggers {@link IcingSearchEngine#optimize()} directly. - * - * <p>This method should be only called as a scheduled task in AppSearch Platform backend. - */ + /** Triggers {@link IcingSearchEngine#optimize()} directly. */ public void optimize() throws AppSearchException { mReadWriteLock.writeLock().lock(); try { diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/FrameworkOptimizeStrategy.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/FrameworkOptimizeStrategy.java new file mode 100644 index 000000000000..8ec30e186306 --- /dev/null +++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/FrameworkOptimizeStrategy.java @@ -0,0 +1,44 @@ +/* + * Copyright 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.appsearch.external.localstorage; + +import android.annotation.NonNull; + +import com.android.internal.annotations.VisibleForTesting; + +import com.google.android.icing.proto.GetOptimizeInfoResultProto; + +/** + * An implementation of {@link OptimizeStrategy} will determine when to trigger {@link + * AppSearchImpl#optimize()} in Jetpack environment. + * + * @hide + */ +public class FrameworkOptimizeStrategy implements OptimizeStrategy { + + @VisibleForTesting static final int DOC_COUNT_OPTIMIZE_THRESHOLD = 100_000; + @VisibleForTesting static final int BYTES_OPTIMIZE_THRESHOLD = 1 * 1024 * 1024 * 1024; // 1GB + + @VisibleForTesting + static final long TIME_OPTIMIZE_THRESHOLD_MILLIS = 7 * 24 * 60 * 60 * 1000; // 1 week + + @Override + public boolean shouldOptimize(@NonNull GetOptimizeInfoResultProto optimizeInfo) { + return optimizeInfo.getOptimizableDocs() >= DOC_COUNT_OPTIMIZE_THRESHOLD + || optimizeInfo.getEstimatedOptimizableBytes() >= BYTES_OPTIMIZE_THRESHOLD + || optimizeInfo.getTimeSinceLastOptimizeMs() >= TIME_OPTIMIZE_THRESHOLD_MILLIS; + } +} diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/OptimizeStrategy.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/OptimizeStrategy.java new file mode 100644 index 000000000000..6cb84bc64eb9 --- /dev/null +++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/OptimizeStrategy.java @@ -0,0 +1,39 @@ +/* + * Copyright 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.appsearch.external.localstorage; + +import android.annotation.NonNull; + +import com.google.android.icing.proto.GetOptimizeInfoResultProto; + +/** + * An interface class for implementing a strategy to determine when to trigger {@link + * AppSearchImpl#optimize()}. + * + * @hide + */ +public interface OptimizeStrategy { + + /** + * Determines whether {@link AppSearchImpl#optimize()} need to be triggered to release garbage + * resources in AppSearch base on the given information. + * + * @param optimizeInfo The proto object indicates the number of garbage resources in AppSearch. + * @return {@code true} if {@link AppSearchImpl#optimize()} need to be triggered. + */ + boolean shouldOptimize(@NonNull GetOptimizeInfoResultProto optimizeInfo); +} diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/CallStats.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/CallStats.java index ea5263aa9aa5..81fb418a6a0a 100644 --- a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/CallStats.java +++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/CallStats.java @@ -18,6 +18,8 @@ package com.android.server.appsearch.external.localstorage.stats; import android.annotation.IntDef; import android.annotation.NonNull; +import android.annotation.Nullable; +import android.app.appsearch.AppSearchResult; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -29,9 +31,9 @@ import java.util.Objects; * <p>This class can set which stats to log for both batch and non-batch {@link * android.app.appsearch.AppSearchSession} calls. * - * <p>Some function calls like {@link android.app.appsearch.AppSearchSession#setSchema} have their - * own detailed stats class {@link placeholder}. However, {@link CallStats} can still be used along - * with the detailed stats class for easy aggregation/analysis with other function calls. + * <p>Some function calls may have their own detailed stats class like {@link PutDocumentStats}. + * However, {@link CallStats} can still be used along with the detailed stats class for easy + * aggregation/analysis with other function calls. * * @hide */ @@ -73,7 +75,16 @@ public class CallStats { public static final int CALL_TYPE_REMOVE_DOCUMENTS_BY_SEARCH = 13; public static final int CALL_TYPE_REMOVE_DOCUMENT_BY_SEARCH = 14; - @NonNull private final GeneralStats mGeneralStats; + @Nullable private final String mPackageName; + @Nullable private final String mDatabase; + /** + * The status code returned by {@link AppSearchResult#getResultCode()} for the call or internal + * state. + */ + @AppSearchResult.ResultCode private final int mStatusCode; + + private final int mTotalLatencyMillis; + @CallType private final int mCallType; private final int mEstimatedBinderLatencyMillis; private final int mNumOperationsSucceeded; @@ -81,17 +92,37 @@ public class CallStats { CallStats(@NonNull Builder builder) { Objects.requireNonNull(builder); - mGeneralStats = Objects.requireNonNull(builder.mGeneralStatsBuilder).build(); + mPackageName = builder.mPackageName; + mDatabase = builder.mDatabase; + mStatusCode = builder.mStatusCode; + mTotalLatencyMillis = builder.mTotalLatencyMillis; mCallType = builder.mCallType; mEstimatedBinderLatencyMillis = builder.mEstimatedBinderLatencyMillis; mNumOperationsSucceeded = builder.mNumOperationsSucceeded; mNumOperationsFailed = builder.mNumOperationsFailed; } - /** Returns general information for the call. */ - @NonNull - public GeneralStats getGeneralStats() { - return mGeneralStats; + /** Returns calling package name. */ + @Nullable + public String getPackageName() { + return mPackageName; + } + + /** Returns calling database name. */ + @Nullable + public String getDatabase() { + return mDatabase; + } + + /** Returns status code for this api call. */ + @AppSearchResult.ResultCode + public int getStatusCode() { + return mStatusCode; + } + + /** Returns total latency of this api call in millis. */ + public int getTotalLatencyMillis() { + return mTotalLatencyMillis; } /** Returns type of the call. */ @@ -137,23 +168,41 @@ public class CallStats { /** Builder for {@link CallStats}. */ public static class Builder { - @NonNull final GeneralStats.Builder mGeneralStatsBuilder; + @Nullable String mPackageName; + @Nullable String mDatabase; + @AppSearchResult.ResultCode int mStatusCode; + int mTotalLatencyMillis; @CallType int mCallType; int mEstimatedBinderLatencyMillis; int mNumOperationsSucceeded; int mNumOperationsFailed; - /** Builder takes {@link GeneralStats.Builder}. */ - public Builder(@NonNull String packageName, @NonNull String database) { - Objects.requireNonNull(packageName); - Objects.requireNonNull(database); - mGeneralStatsBuilder = new GeneralStats.Builder(packageName, database); + /** Sets the PackageName used by the session. */ + @NonNull + public Builder setPackageName(@NonNull String packageName) { + mPackageName = Objects.requireNonNull(packageName); + return this; + } + + /** Sets the database used by the session. */ + @NonNull + public Builder setDatabase(@NonNull String database) { + mDatabase = Objects.requireNonNull(database); + return this; } - /** Returns {@link GeneralStats.Builder}. */ + /** Sets the status code. */ @NonNull - public GeneralStats.Builder getGeneralStatsBuilder() { - return mGeneralStatsBuilder; + public Builder setStatusCode(@AppSearchResult.ResultCode int statusCode) { + mStatusCode = statusCode; + return this; + } + + /** Sets total latency in millis. */ + @NonNull + public Builder setTotalLatencyMillis(int totalLatencyMillis) { + mTotalLatencyMillis = totalLatencyMillis; + return this; } /** Sets type of the call. */ diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/GeneralStats.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/GeneralStats.java deleted file mode 100644 index 53c1ee3f675f..000000000000 --- a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/GeneralStats.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.appsearch.external.localstorage.stats; - -import android.annotation.NonNull; -import android.app.appsearch.AppSearchResult; - -import java.util.Objects; - -/** - * A class for holding general logging information. - * - * <p>This class cannot be logged by {@link - * com.android.server.appsearch.external.localstorage.AppSearchLogger} directly. It is used for - * defining general logging information that is shared across different stats classes. - * - * @see PutDocumentStats - * @see CallStats - * @hide - */ -public final class GeneralStats { - /** Package name of the application. */ - @NonNull private final String mPackageName; - - /** Database name within AppSearch. */ - @NonNull private final String mDatabase; - - /** - * The status code returned by {@link AppSearchResult#getResultCode()} for the call or internal - * state. - */ - @AppSearchResult.ResultCode private final int mStatusCode; - - private final int mTotalLatencyMillis; - - GeneralStats(@NonNull Builder builder) { - Objects.requireNonNull(builder); - mPackageName = Objects.requireNonNull(builder.mPackageName); - mDatabase = Objects.requireNonNull(builder.mDatabase); - mStatusCode = builder.mStatusCode; - mTotalLatencyMillis = builder.mTotalLatencyMillis; - } - - /** Returns package name. */ - @NonNull - public String getPackageName() { - return mPackageName; - } - - /** Returns database name. */ - @NonNull - public String getDatabase() { - return mDatabase; - } - - /** Returns result code from {@link AppSearchResult#getResultCode()} */ - @AppSearchResult.ResultCode - public int getStatusCode() { - return mStatusCode; - } - - /** Returns total latency, in milliseconds. */ - public int getTotalLatencyMillis() { - return mTotalLatencyMillis; - } - - /** Builder for {@link GeneralStats}. */ - public static class Builder { - @NonNull final String mPackageName; - @NonNull final String mDatabase; - @AppSearchResult.ResultCode int mStatusCode = AppSearchResult.RESULT_UNKNOWN_ERROR; - int mTotalLatencyMillis; - - /** - * Constructor - * - * @param packageName name of the package logging stats - * @param database name of the database logging stats - */ - public Builder(@NonNull String packageName, @NonNull String database) { - mPackageName = Objects.requireNonNull(packageName); - mDatabase = Objects.requireNonNull(database); - } - - /** Sets status code returned from {@link AppSearchResult#getResultCode()} */ - @NonNull - public Builder setStatusCode(@AppSearchResult.ResultCode int statusCode) { - mStatusCode = statusCode; - return this; - } - - /** Sets total latency, in milliseconds. */ - @NonNull - public Builder setTotalLatencyMillis(int totalLatencyMillis) { - mTotalLatencyMillis = totalLatencyMillis; - return this; - } - - /** - * Creates a new {@link GeneralStats} object from the contents of this {@link Builder} - * instance. - */ - @NonNull - public GeneralStats build() { - return new GeneralStats(/* builder= */ this); - } - } -} diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/PutDocumentStats.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/PutDocumentStats.java index d031172d29c1..7ba181668bfd 100644 --- a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/PutDocumentStats.java +++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/PutDocumentStats.java @@ -17,6 +17,7 @@ package com.android.server.appsearch.external.localstorage.stats; import android.annotation.NonNull; +import android.app.appsearch.AppSearchResult; import java.util.Objects; @@ -27,8 +28,15 @@ import java.util.Objects; * @hide */ public final class PutDocumentStats { - /** {@link GeneralStats} holds the general stats. */ - @NonNull private final GeneralStats mGeneralStats; + @NonNull private final String mPackageName; + @NonNull private final String mDatabase; + /** + * The status code returned by {@link AppSearchResult#getResultCode()} for the call or internal + * state. + */ + @AppSearchResult.ResultCode private final int mStatusCode; + + private final int mTotalLatencyMillis; /** Time used to generate a document proto from a Bundle. */ private final int mGenerateDocumentProtoLatencyMillis; @@ -61,7 +69,10 @@ public final class PutDocumentStats { PutDocumentStats(@NonNull Builder builder) { Objects.requireNonNull(builder); - mGeneralStats = Objects.requireNonNull(builder.mGeneralStatsBuilder).build(); + mPackageName = builder.mPackageName; + mDatabase = builder.mDatabase; + mStatusCode = builder.mStatusCode; + mTotalLatencyMillis = builder.mTotalLatencyMillis; mGenerateDocumentProtoLatencyMillis = builder.mGenerateDocumentProtoLatencyMillis; mRewriteDocumentTypesLatencyMillis = builder.mRewriteDocumentTypesLatencyMillis; mNativeLatencyMillis = builder.mNativeLatencyMillis; @@ -73,10 +84,27 @@ public final class PutDocumentStats { mNativeExceededMaxNumTokens = builder.mNativeExceededMaxNumTokens; } - /** Returns the {@link GeneralStats} object attached to this instance. */ + /** Returns calling package name. */ + @NonNull + public String getPackageName() { + return mPackageName; + } + + /** Returns calling database name. */ @NonNull - public GeneralStats getGeneralStats() { - return mGeneralStats; + public String getDatabase() { + return mDatabase; + } + + /** Returns status code for this putDocument. */ + @AppSearchResult.ResultCode + public int getStatusCode() { + return mStatusCode; + } + + /** Returns total latency of this putDocument in millis. */ + public int getTotalLatencyMillis() { + return mTotalLatencyMillis; } /** Returns time spent on generating document proto, in milliseconds. */ @@ -129,7 +157,10 @@ public final class PutDocumentStats { /** Builder for {@link PutDocumentStats}. */ public static class Builder { - @NonNull final GeneralStats.Builder mGeneralStatsBuilder; + @NonNull final String mPackageName; + @NonNull final String mDatabase; + @AppSearchResult.ResultCode int mStatusCode; + int mTotalLatencyMillis; int mGenerateDocumentProtoLatencyMillis; int mRewriteDocumentTypesLatencyMillis; int mNativeLatencyMillis; @@ -140,17 +171,24 @@ public final class PutDocumentStats { int mNativeNumTokensIndexed; boolean mNativeExceededMaxNumTokens; - /** Builder takes {@link GeneralStats.Builder}. */ + /** Builder for {@link PutDocumentStats} */ public Builder(@NonNull String packageName, @NonNull String database) { - Objects.requireNonNull(packageName); - Objects.requireNonNull(database); - mGeneralStatsBuilder = new GeneralStats.Builder(packageName, database); + mPackageName = Objects.requireNonNull(packageName); + mDatabase = Objects.requireNonNull(database); } - /** Returns {@link GeneralStats.Builder}. */ + /** Sets the status code. */ @NonNull - public GeneralStats.Builder getGeneralStatsBuilder() { - return mGeneralStatsBuilder; + public Builder setStatusCode(@AppSearchResult.ResultCode int statusCode) { + mStatusCode = statusCode; + return this; + } + + /** Sets total latency in millis. */ + @NonNull + public Builder setTotalLatencyMillis(int totalLatencyMillis) { + mTotalLatencyMillis = totalLatencyMillis; + return this; } /** Sets how much time we spend for generating document proto, in milliseconds. */ 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 cb65e42696d1..ea00f506b47f 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.annotation.NonNull; 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 @@ import java.util.Objects; * <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 @@ public final class LoggerInstanceManager { /** * 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 c857fb602eec..31fead5e6314 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 @@ -29,6 +29,7 @@ import android.util.SparseIntArray; 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; @@ -60,15 +61,15 @@ public final class PlatformLogger implements AppSearchLogger { // 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 @@ public final class PlatformLogger implements AppSearchLogger { 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 @@ public final class PlatformLogger implements AppSearchLogger { * 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 @@ public final class PlatformLogger implements AppSearchLogger { } @Override - public void logStats(@androidx.annotation.NonNull RemoveStats stats) throws AppSearchException { + public void logStats(@NonNull RemoveStats stats) throws AppSearchException { // TODO(b/173532925): Log stats } @@ -237,9 +192,8 @@ public final class PlatformLogger implements AppSearchLogger { @GuardedBy("mLock") private void logStatsImplLocked(@NonNull CallStats stats) { mLastPushTimeMillisLocked = SystemClock.elapsedRealtime(); - ExtraStats extraStats = createExtraStatsLocked(stats.getGeneralStats().getPackageName(), - stats.getCallType()); - String database = stats.getGeneralStats().getDatabase(); + ExtraStats extraStats = createExtraStatsLocked(stats.getPackageName(), stats.getCallType()); + String database = stats.getDatabase(); try { int hashCodeForDatabase = calculateHashCodeMd5(database); AppSearchStatsLog.write(AppSearchStatsLog.APP_SEARCH_CALL_STATS_REPORTED, @@ -247,8 +201,8 @@ public final class PlatformLogger implements AppSearchLogger { extraStats.mSkippedSampleCount, extraStats.mPackageUid, hashCodeForDatabase, - stats.getGeneralStats().getStatusCode(), - stats.getGeneralStats().getTotalLatencyMillis(), + stats.getStatusCode(), + stats.getTotalLatencyMillis(), stats.getCallType(), stats.getEstimatedBinderLatencyMillis(), stats.getNumOperationsSucceeded(), @@ -269,9 +223,9 @@ public final class PlatformLogger implements AppSearchLogger { @GuardedBy("mLock") private void logStatsImplLocked(@NonNull PutDocumentStats stats) { mLastPushTimeMillisLocked = SystemClock.elapsedRealtime(); - ExtraStats extraStats = createExtraStatsLocked(stats.getGeneralStats().getPackageName(), - CallStats.CALL_TYPE_PUT_DOCUMENT); - String database = stats.getGeneralStats().getDatabase(); + ExtraStats extraStats = createExtraStatsLocked( + stats.getPackageName(), CallStats.CALL_TYPE_PUT_DOCUMENT); + String database = stats.getDatabase(); try { int hashCodeForDatabase = calculateHashCodeMd5(database); AppSearchStatsLog.write(AppSearchStatsLog.APP_SEARCH_PUT_DOCUMENT_STATS_REPORTED, @@ -279,8 +233,8 @@ public final class PlatformLogger implements AppSearchLogger { extraStats.mSkippedSampleCount, extraStats.mPackageUid, hashCodeForDatabase, - stats.getGeneralStats().getStatusCode(), - stats.getGeneralStats().getTotalLatencyMillis(), + stats.getStatusCode(), + stats.getTotalLatencyMillis(), stats.getGenerateDocumentProtoLatencyMillis(), stats.getRewriteDocumentTypesLatencyMillis(), stats.getNativeLatencyMillis(), @@ -372,7 +326,9 @@ public final class PlatformLogger implements AppSearchLogger { stats.getSchemaStoreRecoveryLatencyMillis(), stats.getDocumentStoreDataStatus(), stats.getDocumentCount(), - stats.getSchemaTypeCount()); + stats.getSchemaTypeCount(), + stats.hasReset(), + stats.getResetStatusCode()); } /** @@ -428,9 +384,12 @@ public final class PlatformLogger implements AppSearchLogger { 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 +409,7 @@ public final class PlatformLogger implements AppSearchLogger { // 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 +419,7 @@ public final class PlatformLogger implements AppSearchLogger { // 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); @@ -502,6 +459,32 @@ public final class PlatformLogger implements AppSearchLogger { return packageUid; } + /** 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(); + } + } + // // Functions below are used for tests only // 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 bf8051b42acd..0b4e196fd0c4 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 f2b2621b22b8..1771b1ddc6b6 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 95ed36898c73..af09210b2c18 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 @@ -66,8 +66,8 @@ import java.util.Set; * @hide */ public class VisibilityStore { - /** No-op user id that won't have any visibility settings. */ - public static final int NO_OP_USER_ID = -1; + /** No-op uid that won't have any visibility settings. */ + public static final int NO_OP_UID = -1; /** Version for the visibility schema */ private static final int SCHEMA_VERSION = 0; @@ -106,7 +106,7 @@ public class VisibilityStore { * @param userContext Context of the user that the call is being made as */ public VisibilityStore(@NonNull AppSearchImpl appSearchImpl, @NonNull Context userContext) { - mAppSearchImpl = appSearchImpl; + mAppSearchImpl = Objects.requireNonNull(appSearchImpl); mUserContext = Objects.requireNonNull(userContext); } diff --git a/apex/appsearch/synced_jetpack_changeid.txt b/apex/appsearch/synced_jetpack_changeid.txt index 395292df120a..78d39cc6deac 100644 --- a/apex/appsearch/synced_jetpack_changeid.txt +++ b/apex/appsearch/synced_jetpack_changeid.txt @@ -1 +1 @@ -c35ced970a63a6c7b1d17f9706160579540850d6 +31a54dba5bda4d0109ea91eb1ac047c937cbaae3 diff --git a/apex/jobscheduler/framework/java/android/app/AlarmManager.java b/apex/jobscheduler/framework/java/android/app/AlarmManager.java index 9fa7810ab155..1efe5cb2f53e 100644 --- a/apex/jobscheduler/framework/java/android/app/AlarmManager.java +++ b/apex/jobscheduler/framework/java/android/app/AlarmManager.java @@ -662,10 +662,19 @@ public class AlarmManager { * 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 @@ public class AlarmManager { * @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 @@ public class AlarmManager { * 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 @@ public class AlarmManager { * 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 @@ public class AlarmManager { * @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 @@ public class AlarmManager { * 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 @@ public class AlarmManager { * @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 cef065ddac9e..0e9efbcc98b8 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 @@ public class DeviceIdleController extends SystemService @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 @@ public class DeviceIdleController extends SystemService } } } 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 @@ public class DeviceIdleController extends SystemService // 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 @@ public class DeviceIdleController extends SystemService 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 1169391d2cd2..fe0c7f718bb0 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.JobSchedulerBackgroundThread; 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 @@ public class AlarmManagerService extends SystemService { 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 @@ public class AlarmManagerService extends SystemService { 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 @@ public class AlarmManagerService extends SystemService { 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 class AlarmManagerService extends SystemService { */ 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 @@ public class AlarmManagerService extends SystemService { 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 @@ public class AlarmManagerService extends SystemService { } 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 @@ public class AlarmManagerService extends SystemService { 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 @@ public class AlarmManagerService extends SystemService { 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 @@ public class AlarmManagerService extends SystemService { @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 @@ public class AlarmManagerService extends SystemService { } } + 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 @@ public class AlarmManagerService extends SystemService { } 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 @@ public class AlarmManagerService extends SystemService { } }; + 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 @@ public class AlarmManagerService extends SystemService { 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 @@ public class AlarmManagerService extends SystemService { } /** - * 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; - } - 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; + 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); + } } - return !hasScheduleExactAlarmInternal(a.packageName, a.uid); - }; - removeAlarmsInternalLocked(whichAlarms, REMOVE_REASON_EXACT_PERMISSION_REVOKED); + } } /** @@ -3396,9 +3572,7 @@ public class AlarmManagerService extends SystemService { */ 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 @@ public class AlarmManagerService extends SystemService { 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 @@ public class AlarmManagerService extends SystemService { 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 class AlarmManagerService extends SystemService { 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 @@ public class AlarmManagerService extends SystemService { 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 @@ public class AlarmManagerService extends SystemService { 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 2b4b3f0f52e8..f2e64ce0b2c5 100644 --- a/apex/media/Android.bp +++ b/apex/media/Android.bp @@ -28,5 +28,8 @@ package { sdk { name: "media-module-sdk", bootclasspath_fragments: ["com.android.media-bootclasspath-fragment"], - java_sdk_libs: ["service-media-s"], + 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 7697359e7caf..e76d61cf8965 100644 --- a/apex/media/framework/java/android/media/MediaSession2.java +++ b/apex/media/framework/java/android/media/MediaSession2.java @@ -469,7 +469,9 @@ public class MediaSession2 implements AutoCloseable { } 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/cmds/app_process/Android.bp b/cmds/app_process/Android.bp index 0eff83c99282..a1575173ded6 100644 --- a/cmds/app_process/Android.bp +++ b/cmds/app_process/Android.bp @@ -29,7 +29,16 @@ cc_binary { }, }, - ldflags: ["-Wl,--export-dynamic"], + // Symbols exported from the executable in .dynsym interpose symbols in every + // linker namespace, including an app's classloader namespace. Provide this + // version script to prevent unwanted interposition. + // + // By default, the static linker doesn't export most of an executable's symbols, + // but it will export a symbol that appears to override a symbol in a needed DSO. + // This commonly happens with C++ vaguely-linked entities, such as template + // functions or type_info variables. Hence, a version script is needed even for + // an executable. + version_script: "version-script.txt", shared_libs: [ "libandroid_runtime", diff --git a/cmds/app_process/version-script.txt b/cmds/app_process/version-script.txt new file mode 100644 index 000000000000..a98066a67675 --- /dev/null +++ b/cmds/app_process/version-script.txt @@ -0,0 +1,4 @@ +{ + local: + *; +}; diff --git a/core/api/test-current.txt b/core/api/test-current.txt index 620323976067..80664ed0816f 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -77,7 +77,7 @@ package android.accessibilityservice { } 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 { @@ -1113,6 +1113,10 @@ package android.hardware.camera2 { method @RequiresPermission(android.Manifest.permission.CAMERA_OPEN_CLOSE_LISTENER) public void onCameraOpened(@NonNull String, @NonNull String); } + public abstract class CameraMetadata<TKey> { + field public static final int SENSOR_TEST_PATTERN_MODE_BLACK = 5; // 0x5 + } + } package android.hardware.devicestate { @@ -2719,6 +2723,7 @@ package android.view { public final class InputDevice implements android.os.Parcelable { method @RequiresPermission("android.permission.DISABLE_INPUT_DEVICE") public void disable(); method @RequiresPermission("android.permission.DISABLE_INPUT_DEVICE") public void enable(); + field public static final int ACCESSIBILITY_DEVICE_ID = -2; // 0xfffffffe } public class KeyEvent extends android.view.InputEvent implements android.os.Parcelable { @@ -3185,6 +3190,7 @@ package android.window { method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) public java.util.List<android.app.ActivityManager.RunningTaskInfo> getChildTasks(@NonNull android.window.WindowContainerToken, @NonNull int[]); method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) public android.window.WindowContainerToken getImeTarget(int); method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) public java.util.List<android.app.ActivityManager.RunningTaskInfo> getRootTasks(int, @NonNull int[]); + method @BinderThread public void onAppSplashScreenViewRemoved(int); method @BinderThread public void onBackPressedOnTaskRoot(@NonNull android.app.ActivityManager.RunningTaskInfo); method @BinderThread public void onTaskAppeared(@NonNull android.app.ActivityManager.RunningTaskInfo, @NonNull android.view.SurfaceControl); method @BinderThread public void onTaskInfoChanged(@NonNull android.app.ActivityManager.RunningTaskInfo); diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java index 483defab43c9..e91209c1a273 100644 --- a/core/java/android/accessibilityservice/AccessibilityService.java +++ b/core/java/android/accessibilityservice/AccessibilityService.java @@ -685,7 +685,7 @@ public abstract class AccessibilityService extends Service { * @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/Activity.java b/core/java/android/app/Activity.java index 854c9f2a5b3a..db5dcc5c264b 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -3866,9 +3866,26 @@ public class Activity extends ContextThemeWrapper } /** - * Called when the activity has detected the user's press of the back - * key. The default implementation simply finishes the current activity, - * but you can override this to do whatever you want. + * Called when the activity has detected the user's press of the back key. The default + * implementation depends on the platform version: + * + * <ul> + * <li>On platform versions prior to {@link android.os.Build.VERSION_CODES#S}, it + * finishes the current activity, but you can override this to do whatever you want. + * + * <li><p>Starting with platform version {@link android.os.Build.VERSION_CODES#S}, for + * activities that are the root activity of the task and also declare an + * {@link android.content.IntentFilter} with {@link Intent#ACTION_MAIN} and + * {@link Intent#CATEGORY_LAUNCHER} in the manifest, the current activity and its + * task will be moved to the back of the activity stack instead of being finished. + * Other activities will simply be finished. + * + * <p>If you target version {@link android.os.Build.VERSION_CODES#S} or later and + * override this method, it is strongly recommended to call through to the superclass + * implementation after you finish handling navigation within the app. + * </ul> + * + * @see #moveTaskToBack(boolean) */ public void onBackPressed() { if (mActionBar != null && mActionBar.collapseActionView()) { diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index 7cb8bc0d80fd..317e51c27d90 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -254,6 +254,9 @@ public abstract class ActivityManagerInternal { /** 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); diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java index 1ce598b5fa18..8e1f263ebf03 100644 --- a/core/java/android/app/ActivityOptions.java +++ b/core/java/android/app/ActivityOptions.java @@ -419,7 +419,7 @@ public class ActivityOptions { private IBinder mLaunchCookie; private IRemoteTransition mRemoteTransition; private boolean mOverrideTaskTransition; - private int mSplashScreenThemeResId; + private String mSplashScreenThemeResName; @SplashScreen.SplashScreenStyle private int mSplashScreenStyle; private boolean mRemoveWithTaskOrganizer; @@ -1174,7 +1174,7 @@ public class ActivityOptions { mRemoteTransition = IRemoteTransition.Stub.asInterface(opts.getBinder( KEY_REMOTE_TRANSITION)); mOverrideTaskTransition = opts.getBoolean(KEY_OVERRIDE_TASK_TRANSITION); - mSplashScreenThemeResId = opts.getInt(KEY_SPLASH_SCREEN_THEME); + mSplashScreenThemeResName = opts.getString(KEY_SPLASH_SCREEN_THEME); mRemoveWithTaskOrganizer = opts.getBoolean(KEY_REMOVE_WITH_TASK_ORGANIZER); mLaunchedFromBubble = opts.getBoolean(KEY_LAUNCHED_FROM_BUBBLE); mTransientLaunch = opts.getBoolean(KEY_TRANSIENT_LAUNCH); @@ -1368,8 +1368,9 @@ public class ActivityOptions { * Gets whether the activity want to be launched as other theme for the splash screen. * @hide */ - public int getSplashScreenThemeResId() { - return mSplashScreenThemeResId; + @Nullable + public String getSplashScreenThemeResName() { + return mSplashScreenThemeResName; } /** @@ -1945,8 +1946,8 @@ public class ActivityOptions { if (mOverrideTaskTransition) { b.putBoolean(KEY_OVERRIDE_TASK_TRANSITION, mOverrideTaskTransition); } - if (mSplashScreenThemeResId != 0) { - b.putInt(KEY_SPLASH_SCREEN_THEME, mSplashScreenThemeResId); + if (mSplashScreenThemeResName != null && !mSplashScreenThemeResName.isEmpty()) { + b.putString(KEY_SPLASH_SCREEN_THEME, mSplashScreenThemeResName); } if (mRemoveWithTaskOrganizer) { b.putBoolean(KEY_REMOVE_WITH_TASK_ORGANIZER, mRemoveWithTaskOrganizer); diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index eb14c11e7e3c..96d59b80b479 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -3105,24 +3105,11 @@ public class AppOpsManager { */ 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 6d92201db8ec..f79e0780ecae 100644 --- a/core/java/android/app/ConfigurationController.java +++ b/core/java/android/app/ConfigurationController.java @@ -158,10 +158,9 @@ class ConfigurationController { 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/LoadedApk.java b/core/java/android/app/LoadedApk.java index 62b5ec872320..9ed76c1c13d1 100644 --- a/core/java/android/app/LoadedApk.java +++ b/core/java/android/app/LoadedApk.java @@ -932,6 +932,21 @@ public final class LoadedApk { 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 @@ public final class LoadedApk { } 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 0136a35e3975..e68eb7471e42 100644 --- a/core/java/android/app/PendingIntent.java +++ b/core/java/android/app/PendingIntent.java @@ -365,6 +365,7 @@ public final class PendingIntent implements Parcelable { } 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 edd60473c522..cd82deb13e9b 100644 --- a/core/java/android/app/WallpaperColors.java +++ b/core/java/android/app/WallpaperColors.java @@ -30,6 +30,7 @@ import android.util.Log; 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.Collections; 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 @@ public final class WallpaperColors implements Parcelable { 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 @@ public final class WallpaperColors implements Parcelable { } else { palette = Palette .from(bitmap, new CelebiQuantizer()) - .maximumColorCount(5) + .maximumColorCount(128) .resizeBitmapArea(MAX_WALLPAPER_EXTRACTION_AREA) .generate(); } @@ -278,7 +279,7 @@ public final class WallpaperColors implements Parcelable { /** * 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 @@ public final class WallpaperColors implements Parcelable { * @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; - - 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()); + mAllColors = colorToPopulation; + + 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 5b65795612d0..52c58e162289 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -6845,6 +6845,10 @@ public class DevicePolicyManager { * <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 @@ public class DevicePolicyManager { * @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) { @@ -13876,8 +13884,7 @@ public class DevicePolicyManager { } /** - * 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 67f5c366bc14..a9bec98ce405 100644 --- a/core/java/android/app/admin/DevicePolicyManagerInternal.java +++ b/core/java/android/app/admin/DevicePolicyManagerInternal.java @@ -265,5 +265,4 @@ public abstract class DevicePolicyManagerInternal { */ public abstract void notifyUnsafeOperationStateChanged(DevicePolicySafetyChecker checker, @OperationSafetyReason int reason, boolean isSafe); - } diff --git a/core/java/android/app/people/ConversationChannel.java b/core/java/android/app/people/ConversationChannel.java index 332e159679ae..2bf71b0183c6 100644 --- a/core/java/android/app/people/ConversationChannel.java +++ b/core/java/android/app/people/ConversationChannel.java @@ -36,8 +36,8 @@ public final class ConversationChannel implements Parcelable { 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 @@ public final class ConversationChannel implements Parcelable { boolean hasActiveNotifications) { mShortcutInfo = shortcutInfo; mUid = uid; - mParentNotificationChannel = parentNotificationChannel; - mParentNotificationChannelGroup = parentNotificationChannelGroup; + mNotificationChannel = parentNotificationChannel; + mNotificationChannelGroup = parentNotificationChannelGroup; mLastEventTimestamp = lastEventTimestamp; mHasActiveNotifications = hasActiveNotifications; } @@ -74,8 +74,8 @@ public final class ConversationChannel implements Parcelable { 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 final class ConversationChannel implements Parcelable { 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 final class ConversationChannel implements Parcelable { 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 @@ public final class ConversationChannel implements Parcelable { 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 final class ConversationChannel implements Parcelable { 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 2dbbfdf660aa..e11861f49be8 100644 --- a/core/java/android/app/people/PeopleSpaceTile.java +++ b/core/java/android/app/people/PeopleSpaceTile.java @@ -307,10 +307,10 @@ public class PeopleSpaceTile implements Parcelable { 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 fe99f8532aaa..8a6c85d54896 100644 --- a/core/java/android/app/usage/NetworkStatsManager.java +++ b/core/java/android/app/usage/NetworkStatsManager.java @@ -48,6 +48,7 @@ import android.os.RemoteException; 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 @@ public class NetworkStatsManager { * 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 @@ public class NetworkStatsManager { * 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 @@ public class NetworkStatsManager { * 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 @@ public class NetworkStatsManager { * 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 @@ public class NetworkStatsManager { * 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 @@ public class NetworkStatsManager { * 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 @@ public class NetworkStatsManager { : 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 054b63fbad50..ded5e6e27a68 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.os.SystemProperties; 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 @@ public final class BluetoothAdapter { */ 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 @@ public final class BluetoothAdapter { != 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 @@ public final class BluetoothAdapter { * @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 2dfa91dcba3e..4e5ede74ce46 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.annotation.SystemApi; 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 @@ public final class OobData implements Parcelable { @NonNull @SystemApi public LeBuilder setDeviceName(@NonNull byte[] deviceName) { - Preconditions.checkNotNull(deviceName); + requireNonNull(deviceName); this.mDeviceName = deviceName; return this; } @@ -308,8 +308,8 @@ public final class OobData implements Parcelable { @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 @@ public final class OobData implements Parcelable { @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 @@ public final class OobData implements Parcelable { @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 @@ public final class OobData implements Parcelable { @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 @@ public final class OobData implements Parcelable { @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 @@ public final class OobData implements Parcelable { @NonNull @SystemApi public ClassicBuilder setDeviceName(@NonNull byte[] deviceName) { - Preconditions.checkNotNull(deviceName); + requireNonNull(deviceName); this.mDeviceName = deviceName; return this; } @@ -617,7 +617,7 @@ public final class OobData implements Parcelable { @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 dfef47ddc16e..cb3bf297670f 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.ParcelUuid; 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 final class ScanFilter implements Parcelable { 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 @@ public final class ScanFilter implements Parcelable { @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/pm/AppSearchShortcutInfo.java b/core/java/android/content/pm/AppSearchShortcutInfo.java index 63f93bfa24e5..806091e2158d 100644 --- a/core/java/android/content/pm/AppSearchShortcutInfo.java +++ b/core/java/android/content/pm/AppSearchShortcutInfo.java @@ -423,7 +423,7 @@ public class AppSearchShortcutInfo extends GenericDocument { shortLabelResName, longLabel, longLabelResId, longLabelResName, disabledMessage, disabledMessageResId, disabledMessageResName, categoriesSet, intents, rank, extras, getCreationTimestampMillis(), flags, iconResId, iconResName, bitmapPath, iconUri, - disabledReason, persons, locusId, 0); + disabledReason, persons, locusId, null); si.setImplicitRank(implicitRank); if ((implicitRank & ShortcutInfo.RANK_CHANGED_BIT) != 0) { si.setRankChanged(); diff --git a/core/java/android/content/pm/IPackageInstaller.aidl b/core/java/android/content/pm/IPackageInstaller.aidl index 32fc74f60d15..b0ce6a55e9ba 100644 --- a/core/java/android/content/pm/IPackageInstaller.aidl +++ b/core/java/android/content/pm/IPackageInstaller.aidl @@ -63,4 +63,5 @@ interface IPackageInstaller { void bypassNextStagedInstallerCheck(boolean value); void setAllowUnlimitedSilentUpdates(String installerPackageName); + void setSilentUpdatesThrottleTime(long throttleTimeInSeconds); } diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java index 76712b5ce2dc..a264bebb5d88 100644 --- a/core/java/android/content/pm/ShortcutInfo.java +++ b/core/java/android/content/pm/ShortcutInfo.java @@ -449,7 +449,7 @@ public final class ShortcutInfo implements Parcelable { private int mDisabledReason; - private int mStartingThemeResId; + @Nullable private String mStartingThemeResName; private ShortcutInfo(Builder b) { mUserId = b.mContext.getUserId(); @@ -478,8 +478,9 @@ public final class ShortcutInfo implements Parcelable { mExtras = b.mExtras; mLocusId = b.mLocusId; + mStartingThemeResName = b.mStartingThemeResId != 0 + ? b.mContext.getResources().getResourceName(b.mStartingThemeResId) : null; updateTimestamp(); - mStartingThemeResId = b.mStartingThemeResId; } /** @@ -626,7 +627,7 @@ public final class ShortcutInfo implements Parcelable { // Set this bit. mFlags |= FLAG_KEY_FIELDS_ONLY; } - mStartingThemeResId = source.mStartingThemeResId; + mStartingThemeResName = source.mStartingThemeResName; } /** @@ -950,8 +951,8 @@ public final class ShortcutInfo implements Parcelable { if (source.mLocusId != null) { mLocusId = source.mLocusId; } - if (source.mStartingThemeResId != 0) { - mStartingThemeResId = source.mStartingThemeResId; + if (source.mStartingThemeResName != null && !source.mStartingThemeResName.isEmpty()) { + mStartingThemeResName = source.mStartingThemeResName; } } @@ -1454,11 +1455,12 @@ public final class ShortcutInfo implements Parcelable { } /** - * Returns the theme resource id used for the splash screen. + * Returns the theme resource name used for the splash screen. * @hide */ - public int getStartingThemeResId() { - return mStartingThemeResId; + @Nullable + public String getStartingThemeResName() { + return mStartingThemeResName; } /** @hide -- old signature, the internal code still uses it. */ @@ -2182,7 +2184,7 @@ public final class ShortcutInfo implements Parcelable { mPersons = source.readParcelableArray(cl, Person.class); mLocusId = source.readParcelable(cl); mIconUri = source.readString8(); - mStartingThemeResId = source.readInt(); + mStartingThemeResName = source.readString8(); } @Override @@ -2234,7 +2236,7 @@ public final class ShortcutInfo implements Parcelable { dest.writeParcelableArray(mPersons, flags); dest.writeParcelable(mLocusId, flags); dest.writeString8(mIconUri); - dest.writeInt(mStartingThemeResId); + dest.writeString8(mStartingThemeResName); } public static final @NonNull Creator<ShortcutInfo> CREATOR = @@ -2391,10 +2393,10 @@ public final class ShortcutInfo implements Parcelable { sb.append("disabledReason="); sb.append(getDisabledReasonDebugString(mDisabledReason)); - if (mStartingThemeResId != 0) { + if (mStartingThemeResName != null && !mStartingThemeResName.isEmpty()) { addIndentOrComma(sb, indent); - sb.append("SplashScreenThemeResId="); - sb.append(Integer.toHexString(mStartingThemeResId)); + sb.append("SplashScreenThemeResName="); + sb.append(mStartingThemeResName); } addIndentOrComma(sb, indent); @@ -2482,7 +2484,8 @@ public final class ShortcutInfo implements Parcelable { Set<String> categories, Intent[] intentsWithExtras, int rank, PersistableBundle extras, long lastChangedTimestamp, int flags, int iconResId, String iconResName, String bitmapPath, String iconUri, - int disabledReason, Person[] persons, LocusId locusId, int startingThemeResId) { + int disabledReason, Person[] persons, LocusId locusId, + @Nullable String startingThemeResName) { mUserId = userId; mId = id; mPackageName = packageName; @@ -2511,6 +2514,6 @@ public final class ShortcutInfo implements Parcelable { mDisabledReason = disabledReason; mPersons = persons; mLocusId = locusId; - mStartingThemeResId = startingThemeResId; + mStartingThemeResName = startingThemeResName; } } diff --git a/core/java/android/content/pm/ShortcutServiceInternal.java b/core/java/android/content/pm/ShortcutServiceInternal.java index 233abf36131b..3ed5c6457fa5 100644 --- a/core/java/android/content/pm/ShortcutServiceInternal.java +++ b/core/java/android/content/pm/ShortcutServiceInternal.java @@ -74,7 +74,7 @@ public abstract class ShortcutServiceInternal { /** * Get the theme res ID of the starting window, it can be 0 if not specified. */ - public abstract int getShortcutStartingThemeResId(int launcherUserId, + public abstract @Nullable String getShortcutStartingThemeResName(int launcherUserId, @NonNull String callingPackage, @NonNull String packageName, @NonNull String shortcutId, int userId); diff --git a/core/java/android/content/pm/parsing/ApkLiteParseUtils.java b/core/java/android/content/pm/parsing/ApkLiteParseUtils.java index 1e650a807cec..154d9234d00c 100644 --- a/core/java/android/content/pm/parsing/ApkLiteParseUtils.java +++ b/core/java/android/content/pm/parsing/ApkLiteParseUtils.java @@ -493,6 +493,7 @@ public class ApkLiteParseUtils { if (targetResult.isError()) { return input.error(targetResult); } + targetSdkVersion = targetResult.getResult(); ParseResult<Integer> minResult = ParsingPackageUtils.computeMinSdkVersion( minVer, minCode, ParsingPackageUtils.SDK_VERSION, @@ -500,8 +501,6 @@ public class ApkLiteParseUtils { if (minResult.isError()) { return input.error(minResult); } - - targetSdkVersion = targetResult.getResult(); minSdkVersion = minResult.getResult(); } } diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java index d50404e94544..24c6a5a12178 100644 --- a/core/java/android/content/res/AssetManager.java +++ b/core/java/android/content/res/AssetManager.java @@ -43,6 +43,7 @@ import java.io.FileDescriptor; 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 @@ public final class AssetManager implements AutoCloseable { 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 @@ public final class AssetManager implements AutoCloseable { } } + 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 @@ public final class AssetManager implements AutoCloseable { // 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 ac4b7b7dc158..12e41e299e16 100644 --- a/core/java/android/content/res/Resources.java +++ b/core/java/android/content/res/Resources.java @@ -341,7 +341,7 @@ public class Resources { /** * 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 @@ public class Resources { 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 @@ public class Resources { } } - 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 @@ public class Resources { } } + 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 553e11b46da5..b9f93b85f0bf 100644 --- a/core/java/android/content/res/ResourcesImpl.java +++ b/core/java/android/content/res/ResourcesImpl.java @@ -54,6 +54,8 @@ import android.view.DisplayAdjustments; import com.android.internal.util.GrowingArrayUtils; +import libcore.util.NativeAllocationRegistry; + import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -1265,15 +1267,9 @@ public class ResourcesImpl { 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 @@ public class ResourcesImpl { 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 @@ public class ResourcesImpl { /*package*/ ThemeImpl() { mAssets = ResourcesImpl.this.mAssets; mTheme = mAssets.createTheme(); + sThemeRegistry.registerNativeAllocation(this, mTheme); } @Override @@ -1404,14 +1401,18 @@ public class ResourcesImpl { * {@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 bc2dcb3b4e62..fe8dc46aff4d 100644 --- a/core/java/android/hardware/SystemSensorManager.java +++ b/core/java/android/hardware/SystemSensorManager.java @@ -571,7 +571,9 @@ public class SystemSensorManager extends SensorManager { } 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 @@ public class SystemSensorManager extends SensorManager { 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 @@ public class SystemSensorManager extends SensorManager { 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/biometrics/ParentalControlsUtilsInternal.java b/core/java/android/hardware/biometrics/ParentalControlsUtilsInternal.java new file mode 100644 index 000000000000..4ec6f0d2509e --- /dev/null +++ b/core/java/android/hardware/biometrics/ParentalControlsUtilsInternal.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.biometrics; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.app.admin.DevicePolicyManager; +import android.content.ComponentName; +import android.content.Context; +import android.os.Build; +import android.os.UserHandle; +import android.provider.Settings; + +/** + * "Base" functionality. For settings-specific functionality (which may rely on this base + * functionality), see {@link com.android.settings.biometrics.ParentalControlsUtils} + * @hide + */ +public class ParentalControlsUtilsInternal { + + private static final String TEST_ALWAYS_REQUIRE_CONSENT = + "android.hardware.biometrics.ParentalControlsUtilsInternal.always_require_consent"; + + public static boolean isTestModeEnabled(@NonNull Context context) { + if (Build.IS_USERDEBUG || Build.IS_ENG) { + return Settings.Secure.getInt(context.getContentResolver(), + TEST_ALWAYS_REQUIRE_CONSENT, 0) != 0; + } + return false; + } + + public static boolean parentConsentRequired(@NonNull Context context, + @NonNull DevicePolicyManager dpm, @BiometricAuthenticator.Modality int modality, + @NonNull UserHandle userHandle) { + if (isTestModeEnabled(context)) { + return true; + } + + return parentConsentRequired(dpm, modality, userHandle); + } + + /** + * @return true if parental consent is required in order for biometric sensors to be used. + */ + public static boolean parentConsentRequired(@NonNull DevicePolicyManager dpm, + @BiometricAuthenticator.Modality int modality, @NonNull UserHandle userHandle) { + final ComponentName cn = getSupervisionComponentName(dpm, userHandle); + if (cn == null) { + return false; + } + + final int keyguardDisabledFeatures = dpm.getKeyguardDisabledFeatures(cn); + final boolean dpmFpDisabled = containsFlag(keyguardDisabledFeatures, + DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT); + final boolean dpmFaceDisabled = containsFlag(keyguardDisabledFeatures, + DevicePolicyManager.KEYGUARD_DISABLE_FACE); + final boolean dpmIrisDisabled = containsFlag(keyguardDisabledFeatures, + DevicePolicyManager.KEYGUARD_DISABLE_IRIS); + + final boolean consentRequired; + if (containsFlag(modality, BiometricAuthenticator.TYPE_FINGERPRINT) && dpmFpDisabled) { + consentRequired = true; + } else if (containsFlag(modality, BiometricAuthenticator.TYPE_FACE) && dpmFaceDisabled) { + consentRequired = true; + } else if (containsFlag(modality, BiometricAuthenticator.TYPE_IRIS) && dpmIrisDisabled) { + consentRequired = true; + } else { + consentRequired = false; + } + + return consentRequired; + } + + @Nullable + public static ComponentName getSupervisionComponentName(@NonNull DevicePolicyManager dpm, + @NonNull UserHandle userHandle) { + return dpm.getProfileOwnerOrDeviceOwnerSupervisionComponent(userHandle); + } + + private static boolean containsFlag(int haystack, int needle) { + return (haystack & needle) != 0; + } +} diff --git a/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java b/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java index 8e3de616f07b..41272437c407 100644 --- a/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java +++ b/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java @@ -693,20 +693,42 @@ public final class CameraExtensionCharacteristics { 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/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java index d4da3b9526c3..9501994fe38a 100644 --- a/core/java/android/hardware/camera2/CameraMetadata.java +++ b/core/java/android/hardware/camera2/CameraMetadata.java @@ -17,6 +17,7 @@ package android.hardware.camera2; import android.annotation.NonNull; +import android.annotation.TestApi; import android.compat.annotation.UnsupportedAppUsage; import android.hardware.camera2.impl.CameraMetadataNative; import android.hardware.camera2.impl.PublicKey; @@ -2922,10 +2923,10 @@ public abstract class CameraMetadata<TKey> { * respective color channel provided in * {@link CaptureRequest#SENSOR_TEST_PATTERN_DATA android.sensor.testPatternData}.</p> * <p>For example:</p> - * <pre><code>android.control.testPatternData = [0, 0xFFFFFFFF, 0xFFFFFFFF, 0] + * <pre><code>{@link CaptureRequest#SENSOR_TEST_PATTERN_DATA android.sensor.testPatternData} = [0, 0xFFFFFFFF, 0xFFFFFFFF, 0] * </code></pre> * <p>All green pixels are 100% green. All red/blue pixels are black.</p> - * <pre><code>android.control.testPatternData = [0xFFFFFFFF, 0, 0xFFFFFFFF, 0] + * <pre><code>{@link CaptureRequest#SENSOR_TEST_PATTERN_DATA android.sensor.testPatternData} = [0xFFFFFFFF, 0, 0xFFFFFFFF, 0] * </code></pre> * <p>All red pixels are 100% red. Only the odd green pixels * are 100% green. All blue pixels are 100% black.</p> @@ -3002,6 +3003,20 @@ public abstract class CameraMetadata<TKey> { public static final int SENSOR_TEST_PATTERN_MODE_PN9 = 4; /** + * <p>All pixel data is replaced by 0% intensity (black) values.</p> + * <p>This test pattern is identical to SOLID_COLOR with a value of <code>[0, 0, 0, 0]</code> for + * {@link CaptureRequest#SENSOR_TEST_PATTERN_DATA android.sensor.testPatternData}. It is recommended that devices implement full + * SOLID_COLOR support instead, but BLACK can be used to provide minimal support for a + * test pattern suitable for privacy use cases.</p> + * + * @see CaptureRequest#SENSOR_TEST_PATTERN_DATA + * @see CaptureRequest#SENSOR_TEST_PATTERN_MODE + * @hide + */ + @TestApi + public static final int SENSOR_TEST_PATTERN_MODE_BLACK = 5; + + /** * <p>The first custom test pattern. All custom patterns that are * available only on this camera device are at least this numeric * value.</p> diff --git a/core/java/android/hardware/camera2/extension/IImageCaptureExtenderImpl.aidl b/core/java/android/hardware/camera2/extension/IImageCaptureExtenderImpl.aidl index c04e75ea6758..3ebf63793b79 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.impl.CameraMetadataNative; 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 @@ interface IImageCaptureExtenderImpl @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 f365469eaecc..4c85966c10dc 100644 --- a/core/java/android/hardware/camera2/extension/IImageProcessorImpl.aidl +++ b/core/java/android/hardware/camera2/extension/IImageProcessorImpl.aidl @@ -21,5 +21,6 @@ import android.hardware.camera2.extension.ParcelImage; /** @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 abc487db5bdb..5cf50a25de78 100644 --- a/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java @@ -79,8 +79,8 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes 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 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes 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 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes } } outputList.add(outConfig); - mSurfaceIdMap.put(outConfig.getSurface(), output.outputId.id); + mCameraConfigMap.put(outConfig.getSurface(), output); } SessionConfiguration sessionConfiguration = new SessionConfiguration( @@ -629,7 +629,7 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes 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 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes 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 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes 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 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes 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 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes 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 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes 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 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes } 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 5339f41ecdd6..4bcc4942d8a0 100644 --- a/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java @@ -18,7 +18,6 @@ package android.hardware.camera2.impl; 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.TotalCaptureResult; 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.HashMap; 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 8dfb787bb3ab..5bb7201eff65 100644 --- a/core/java/android/hardware/camera2/params/OutputConfiguration.java +++ b/core/java/android/hardware/camera2/params/OutputConfiguration.java @@ -735,8 +735,7 @@ public final class OutputConfiguration implements Parcelable { 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 @@ public final class OutputConfiguration implements Parcelable { } mPhysicalCameraId = physicalCameraId; mIsMultiResolution = isMultiResolutionOutput; - mSensorPixelModesUsed = sensorPixelModesUsed; + mSensorPixelModesUsed = convertIntArrayToIntegerList(sensorPixelModesUsed); } /** @@ -826,13 +825,7 @@ public final class OutputConfiguration implements Parcelable { 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 @@ public final class OutputConfiguration implements Parcelable { 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 @@ public final class OutputConfiguration implements Parcelable { 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 ea6b92d4f33e..cfb6efa9ba3c 100644 --- a/core/java/android/hardware/camera2/params/SessionConfiguration.java +++ b/core/java/android/hardware/camera2/params/SessionConfiguration.java @@ -146,13 +146,7 @@ public final class SessionConfiguration implements Parcelable { 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 4845ec3e3bd8..c62f6da012c1 100644 --- a/core/java/android/hardware/camera2/params/VendorTagDescriptor.java +++ b/core/java/android/hardware/camera2/params/VendorTagDescriptor.java @@ -36,13 +36,7 @@ public final class VendorTagDescriptor implements Parcelable { 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 450b70bcdcdc..8d7615c98662 100644 --- a/core/java/android/hardware/camera2/params/VendorTagDescriptorCache.java +++ b/core/java/android/hardware/camera2/params/VendorTagDescriptorCache.java @@ -36,13 +36,7 @@ public final class VendorTagDescriptorCache implements Parcelable { 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/AmbientDisplayConfiguration.java b/core/java/android/hardware/display/AmbientDisplayConfiguration.java index 891299760237..a1f7aa12264b 100644 --- a/core/java/android/hardware/display/AmbientDisplayConfiguration.java +++ b/core/java/android/hardware/display/AmbientDisplayConfiguration.java @@ -53,7 +53,8 @@ public class AmbientDisplayConfiguration { || pickupGestureEnabled(user) || tapGestureEnabled(user) || doubleTapGestureEnabled(user) - || quickPickupSensorEnabled(user); + || quickPickupSensorEnabled(user) + || screenOffUdfpsEnabled(user); } /** {@hide} */ @@ -106,6 +107,12 @@ public class AmbientDisplayConfiguration { } /** {@hide} */ + public boolean screenOffUdfpsEnabled(int user) { + return !TextUtils.isEmpty(udfpsLongPressSensorType()) + && boolSettingDefaultOff("screen_off_udfps_enabled", user); + } + + /** {@hide} */ public boolean wakeScreenGestureAvailable() { return mContext.getResources() .getBoolean(R.bool.config_dozeWakeLockScreenSensorAvailable); diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java index df51734bc17d..a9b95fce8777 100644 --- a/core/java/android/hardware/display/DisplayManagerGlobal.java +++ b/core/java/android/hardware/display/DisplayManagerGlobal.java @@ -94,6 +94,7 @@ public final class DisplayManagerGlobal { // Guarded by mLock private boolean mDispatchNativeCallbacks = false; + private float mNativeCallbackReportedRefreshRate; private final Object mLock = new Object(); @UnsupportedAppUsage @@ -404,10 +405,11 @@ public final class DisplayManagerGlobal { // 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 @@ public final class DisplayManagerGlobal { 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 dce3fefff285..c739c6a53167 100644 --- a/core/java/android/hardware/display/DisplayManagerInternal.java +++ b/core/java/android/hardware/display/DisplayManagerInternal.java @@ -287,6 +287,12 @@ public abstract class DisplayManagerInternal { 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 64f20b839a63..5a25cfc00cd4 100644 --- a/core/java/android/net/nsd/NsdManager.java +++ b/core/java/android/net/nsd/NsdManager.java @@ -200,6 +200,9 @@ public final class NsdManager { 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/os/BatteryUsageStats.java b/core/java/android/os/BatteryUsageStats.java index f2857ceb59d7..6c9f0f677db9 100644 --- a/core/java/android/os/BatteryUsageStats.java +++ b/core/java/android/os/BatteryUsageStats.java @@ -75,6 +75,8 @@ public final class BatteryUsageStats implements Parcelable { 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 @@ public final class BatteryUsageStats implements Parcelable { /** 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 @@ public final class BatteryUsageStats implements Parcelable { 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/PackageTagsList.java b/core/java/android/os/PackageTagsList.java index c94d3de33b6f..4a81dc6f592e 100644 --- a/core/java/android/os/PackageTagsList.java +++ b/core/java/android/os/PackageTagsList.java @@ -23,20 +23,26 @@ import android.annotation.TestApi; import android.util.ArrayMap; import android.util.ArraySet; +import com.android.internal.annotations.Immutable; + import java.io.PrintWriter; +import java.util.Collection; import java.util.Map; import java.util.Objects; import java.util.Set; /** - * A list of packages and associated attribution tags that supports easy membership checks. + * A list of packages and associated attribution tags that supports easy membership checks. Supports + * "wildcard" attribution tags (ie, matching any attribution tag under a package) in additional to + * standard checks. * * @hide */ @TestApi +@Immutable public final class PackageTagsList implements Parcelable { - // an empty set value matches any attribution tag + // an empty set value matches any attribution tag (ie, wildcard) private final ArrayMap<String, ArraySet<String>> mPackageTags; private PackageTagsList(@NonNull ArrayMap<String, ArraySet<String>> packageTags) { @@ -51,15 +57,34 @@ public final class PackageTagsList implements Parcelable { } /** - * Returns true if the given package is represented within this instance. If this returns true - * this does not imply anything about whether any given attribution tag under the given package - * name is present. + * Returns true if the given package is found within this instance. If this returns true this + * does not imply anything about whether any given attribution tag under the given package name + * is present. */ public boolean includes(@NonNull String packageName) { return mPackageTags.containsKey(packageName); } /** + * Returns true if the given attribution tag is found within this instance under any package. + * Only returns true if the attribution tag literal is found, not if any package contains the + * set of all attribution tags. + * + * @hide + */ + public boolean includesTag(@NonNull String attributionTag) { + final int size = mPackageTags.size(); + for (int i = 0; i < size; i++) { + ArraySet<String> tags = mPackageTags.valueAt(i); + if (tags.contains(attributionTag)) { + return true; + } + } + + return false; + } + + /** * Returns true if all attribution tags under the given package are contained within this * instance. */ @@ -76,6 +101,7 @@ public final class PackageTagsList implements Parcelable { if (tags == null) { return false; } else if (tags.isEmpty()) { + // our tags are the full set, so we contain any attribution tag return true; } else { return tags.contains(attributionTag); @@ -98,10 +124,12 @@ public final class PackageTagsList implements Parcelable { return false; } if (tags.isEmpty()) { + // our tags are the full set, so we contain whatever the other tags are continue; } ArraySet<String> otherTags = packageTagsList.mPackageTags.valueAt(i); if (otherTags.isEmpty()) { + // other tags are the full set, so we can't contain them return false; } if (!tags.containsAll(otherTags)) { @@ -248,6 +276,31 @@ public final class PackageTagsList implements Parcelable { } /** + * Adds the specified package and set of attribution tags to the builder. + * + * @hide + */ + @SuppressLint("MissingGetterMatchingBuilder") + public @NonNull Builder add(@NonNull String packageName, + @NonNull Collection<String> attributionTags) { + if (attributionTags.isEmpty()) { + // the input is not allowed to specify a full set by passing in an empty collection + return this; + } + + ArraySet<String> tags = mPackageTags.get(packageName); + if (tags == null) { + tags = new ArraySet<>(attributionTags); + mPackageTags.put(packageName, tags); + } else if (!tags.isEmpty()) { + // if we contain the full set, already done, otherwise add all the tags + tags.addAll(attributionTags); + } + + return this; + } + + /** * Adds the specified {@link PackageTagsList} to the builder. */ @SuppressLint("MissingGetterMatchingBuilder") @@ -267,13 +320,92 @@ public final class PackageTagsList implements Parcelable { if (newTags.isEmpty()) { add(entry.getKey()); } else { - ArraySet<String> tags = mPackageTags.get(entry.getKey()); - if (tags == null) { - tags = new ArraySet<>(newTags); - mPackageTags.put(entry.getKey(), tags); - } else if (!tags.isEmpty()) { - tags.addAll(newTags); - } + add(entry.getKey(), newTags); + } + } + + return this; + } + + /** + * Removes all attribution tags under the specified package from the builder. + * + * @hide + */ + @SuppressLint("MissingGetterMatchingBuilder") + public @NonNull Builder remove(@NonNull String packageName) { + mPackageTags.remove(packageName); + return this; + } + + /** + * Removes the specified package and attribution tag from the builder if and only if the + * specified attribution tag is listed explicitly under the package. If the package contains + * all possible attribution tags, then nothing will be removed. + * + * @hide + */ + @SuppressLint("MissingGetterMatchingBuilder") + public @NonNull Builder remove(@NonNull String packageName, + @Nullable String attributionTag) { + ArraySet<String> tags = mPackageTags.get(packageName); + if (tags != null && tags.remove(attributionTag) && tags.isEmpty()) { + mPackageTags.remove(packageName); + } + return this; + } + + /** + * Removes the specified package and set of attribution tags from the builder if and only if + * the specified set of attribution tags are listed explicitly under the package. If the + * package contains all possible attribution tags, then nothing will be removed. + * + * @hide + */ + @SuppressLint("MissingGetterMatchingBuilder") + public @NonNull Builder remove(@NonNull String packageName, + @NonNull Collection<String> attributionTags) { + if (attributionTags.isEmpty()) { + // the input is not allowed to specify a full set by passing in an empty collection + return this; + } + + ArraySet<String> tags = mPackageTags.get(packageName); + if (tags != null && tags.removeAll(attributionTags) && tags.isEmpty()) { + mPackageTags.remove(packageName); + } + return this; + } + + /** + * Removes the specified {@link PackageTagsList} from the builder. If a package contains all + * possible attribution tags, it will only be removed if the package in the removed + * {@link PackageTagsList} also contains all possible attribution tags. + * + * @hide + */ + @SuppressLint("MissingGetterMatchingBuilder") + public @NonNull Builder remove(@NonNull PackageTagsList packageTagsList) { + return remove(packageTagsList.mPackageTags); + } + + /** + * Removes the given map of package to attribution tags to the builder. An empty set of + * attribution tags is interpreted to imply all attribution tags under that package. If a + * package contains all possible attribution tags, it will only be removed if the package in + * the removed map also contains all possible attribution tags. + * + * @hide + */ + @SuppressLint("MissingGetterMatchingBuilder") + public @NonNull Builder remove(@NonNull Map<String, ? extends Set<String>> packageTagsMap) { + for (Map.Entry<String, ? extends Set<String>> entry : packageTagsMap.entrySet()) { + Set<String> removedTags = entry.getValue(); + if (removedTags.isEmpty()) { + // if removing the full set, drop the package completely + remove(entry.getKey()); + } else { + remove(entry.getKey(), removedTags); } } diff --git a/core/java/android/os/TEST_MAPPING b/core/java/android/os/TEST_MAPPING index 97e03e9d0d94..55b1f940c764 100644 --- a/core/java/android/os/TEST_MAPPING +++ b/core/java/android/os/TEST_MAPPING @@ -40,7 +40,12 @@ ] }, { - "file_patterns": ["BatteryStats.java"], + "file_patterns": [ + "BatteryStats[^/]*\\.java", + "BatteryUsageStats[^/]*\\.java", + "PowerComponents\\.java", + "[^/]*BatteryConsumer[^/]*\\.java" + ], "name": "FrameworksCoreTests", "options": [ { "include-filter": "com.android.internal.os.BatteryStatsTests" }, @@ -48,13 +53,26 @@ ] }, { - "file_patterns": ["BatteryStats.java"], + "file_patterns": [ + "BatteryStats[^/]*\\.java", + "BatteryUsageStats[^/]*\\.java", + "PowerComponents\\.java", + "[^/]*BatteryConsumer[^/]*\\.java" + ], "name": "FrameworksServicesTests", "options": [ { "include-filter": "com.android.server.am.BatteryStatsServiceTest" }, { "include-filter": "com.android.server.am.MeasuredEnergySnapshotTest" }, { "include-filter": "com.android.server.am.BatteryExternalStatsWorkerTest" } ] + }, + { + "file_patterns": [ + "BatteryUsageStats[^/]*\\.java", + "PowerComponents\\.java", + "[^/]*BatteryConsumer[^/]*\\.java" + ], + "name": "BatteryUsageStatsProtoTests" } ], "postsubmit": [ diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index 224cd84bc777..c22224dd0da2 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -575,6 +575,8 @@ public class UserManager { * <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 6e25968192ae..8ebc0814a3dc 100644 --- a/core/java/android/os/incremental/IncrementalFileStorages.java +++ b/core/java/android/os/incremental/IncrementalFileStorages.java @@ -160,7 +160,7 @@ public final class IncrementalFileStorages { /** * 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/service/voice/AlwaysOnHotwordDetector.java b/core/java/android/service/voice/AlwaysOnHotwordDetector.java index fed28df964d6..67b97cee1b51 100644 --- a/core/java/android/service/voice/AlwaysOnHotwordDetector.java +++ b/core/java/android/service/voice/AlwaysOnHotwordDetector.java @@ -354,6 +354,13 @@ public class AlwaysOnHotwordDetector extends AbstractHotwordDetector { 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 @@ public class AlwaysOnHotwordDetector extends AbstractHotwordDetector { } @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 @@ public class AlwaysOnHotwordDetector extends AbstractHotwordDetector { } 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 deb6c01a3088..b66d93d6316e 100644 --- a/core/java/android/service/voice/HotwordDetectionService.java +++ b/core/java/android/service/voice/HotwordDetectionService.java @@ -31,6 +31,7 @@ import android.content.Context; 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 @@ public abstract class HotwordDetectionService extends Service { } @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 72dd45aeeb0f..d7ed67812e87 100644 --- a/core/java/android/service/voice/IHotwordDetectionService.aidl +++ b/core/java/android/service/voice/IHotwordDetectionService.aidl @@ -19,6 +19,7 @@ package android.service.voice; 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 @@ oneway interface IHotwordDetectionService { 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 47f2c6403757..204e7df89706 100644 --- a/core/java/android/service/voice/SoftwareHotwordDetector.java +++ b/core/java/android/service/voice/SoftwareHotwordDetector.java @@ -147,8 +147,9 @@ class SoftwareHotwordDetector extends AbstractHotwordDetector { } @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 f5c959137d9b..c048286545c3 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 @@ public abstract class VoiceInteractionManagerInternal { * 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 603df1e32e8b..05ed75a7d8fb 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -1511,9 +1511,12 @@ public abstract class WallpaperService extends Service { 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(); diff --git a/core/java/android/speech/RecognitionService.java b/core/java/android/speech/RecognitionService.java index b9ff5e7be86a..8b4c0d9e21f5 100644 --- a/core/java/android/speech/RecognitionService.java +++ b/core/java/android/speech/RecognitionService.java @@ -33,10 +33,13 @@ import android.os.Binder; 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,28 @@ public abstract class RecognitionService extends Service { protected abstract void onStopListening(Callback listener); @Override + @SuppressLint("MissingNullability") + 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 +274,7 @@ public abstract class RecognitionService extends Service { 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 +447,7 @@ public abstract class RecognitionService extends Service { } private boolean checkPermissionAndStartDataDelivery() { - if (isPerformingDataDelivery()) { + if (mCurrentCallback.mAttributionContextCreated) { return true; } if (PermissionChecker.checkPermissionAndStartDataDelivery( @@ -441,13 +467,4 @@ public abstract class RecognitionService extends Service { 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 37a97ca719b1..94da93e9a2cf 100644 --- a/core/java/android/speech/SpeechRecognizer.java +++ b/core/java/android/speech/SpeechRecognizer.java @@ -309,11 +309,16 @@ public class SpeechRecognizer { * {@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 91847f740953..7e82cc6318f7 100644 --- a/core/java/android/uwb/AdapterStateListener.java +++ b/core/java/android/uwb/AdapterStateListener.java @@ -108,16 +108,13 @@ public class AdapterStateListener extends IUwbAdapterStateCallbacks.Stub { */ 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/IWindow.aidl b/core/java/android/view/IWindow.aidl index 8d59ba0b1f76..b8b13b9ed88a 100644 --- a/core/java/android/view/IWindow.aidl +++ b/core/java/android/view/IWindow.aidl @@ -65,13 +65,20 @@ oneway interface IWindow { /** * 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/InputDevice.java b/core/java/android/view/InputDevice.java index 4f1354d7eee6..782a992d28e5 100644 --- a/core/java/android/view/InputDevice.java +++ b/core/java/android/view/InputDevice.java @@ -444,6 +444,13 @@ public final class InputDevice implements Parcelable { private static final int VIBRATOR_ID_ALL = -1; + /** + * The device id of input events generated inside accessibility service. + * @hide + */ + @TestApi + public static final int ACCESSIBILITY_DEVICE_ID = -2; + public static final @android.annotation.NonNull Parcelable.Creator<InputDevice> CREATOR = new Parcelable.Creator<InputDevice>() { public InputDevice createFromParcel(Parcel in) { diff --git a/core/java/android/view/ScrollCaptureTarget.java b/core/java/android/view/ScrollCaptureTarget.java index 4fd48892da70..44017ed0d831 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 final class ScrollCaptureTarget { 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 8138b3d30ddf..a8fe875f3485 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -9808,23 +9808,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ 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 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** + * 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 538b8888fa70..73294b3ac969 100644 --- a/core/java/android/view/ViewDebug.java +++ b/core/java/android/view/ViewDebug.java @@ -953,8 +953,7 @@ public class ViewDebug { 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 @@ public class ViewDebug { mQueue.removeLast(); needsInvoke = false; } - picture.writeToStream(mByteStream); - mQueue.add(mByteStream.toByteArray()); - mByteStream.reset(); + mQueue.add(picture); mLock.unlock(); if (needsInvoke) { @@ -1003,7 +1000,7 @@ public class ViewDebug { @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 @@ public class ViewDebug { } 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 67cf85cee9ac..d42e0c367763 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -585,6 +585,10 @@ public final class ViewRootImpl implements ViewParent, 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 @@ public final class ViewRootImpl implements ViewParent, 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 @@ public final class ViewRootImpl implements ViewParent, if (mHardwareRendererObserver != null) { mAttachInfo.mThreadedRenderer.addObserver(mHardwareRendererObserver); } + addASurfaceTransactionCallback(); + mAttachInfo.mThreadedRenderer.setSurfaceControl(mSurfaceControl); } } } @@ -1708,6 +1712,10 @@ public final class ViewRootImpl implements ViewParent, 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 @@ public final class ViewRootImpl implements ViewParent, } } - if (mApplyInsetsRequested) { + if (mApplyInsetsRequested && !(mWillMove || mWillResize)) { dispatchApplyInsets(host); if (mLayoutRequested) { // Short-circuit catching a new layout request here, so @@ -5235,16 +5243,25 @@ public final class ViewRootImpl implements ViewParent, 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 @@ public final class ViewRootImpl implements ViewParent, // 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 @@ public final class ViewRootImpl implements ViewParent, break; } case MSG_WINDOW_MOVED: + mWillMove = false; if (mAdded) { final int w = mWinFrame.width(); final int h = mWinFrame.height(); @@ -7744,6 +7763,8 @@ public final class ViewRootImpl implements ViewParent, mTranslator.translateSourceControlsInScreenToAppWindow(mTempControls); } setFrame(mTmpFrames.frame); + mWillMove = false; + mWillResize = false; mInsetsController.onStateChanged(mTempInsets); mInsetsController.onControlsChanged(mTempControls); return relayoutResult; @@ -8179,7 +8200,8 @@ public final class ViewRootImpl implements ViewParent, 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 @@ public final class ViewRootImpl implements ViewParent, 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 @@ public final class ViewRootImpl implements ViewParent, 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 @@ public final class ViewRootImpl implements ViewParent, } @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/WindowManager.java b/core/java/android/view/WindowManager.java index c1e394d7456a..5964f632da1a 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -2371,6 +2371,14 @@ public interface WindowManager extends ViewManager { public static final int PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY = 0x00100000; /** + * Flag to prevent the window from being magnified by the accessibility magnifier. + * + * TODO(b/190623172): This is a temporary solution and need to find out another way instead. + * @hide + */ + public static final int PRIVATE_FLAG_NOT_MAGNIFIABLE = 0x00400000; + + /** * Flag to indicate that the status bar window is in a state such that it forces showing * the navigation bar unless the navigation bar window is explicitly set to * {@link View#GONE}. @@ -2473,6 +2481,7 @@ public interface WindowManager extends ViewManager { PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE, SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS, PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY, + PRIVATE_FLAG_NOT_MAGNIFIABLE, PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION, PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC, PRIVATE_FLAG_USE_BLAST, @@ -2553,6 +2562,10 @@ public interface WindowManager extends ViewManager { equals = PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY, name = "IS_ROUNDED_CORNERS_OVERLAY"), @ViewDebug.FlagToString( + mask = PRIVATE_FLAG_NOT_MAGNIFIABLE, + equals = PRIVATE_FLAG_NOT_MAGNIFIABLE, + name = "NOT_MAGNIFIABLE"), + @ViewDebug.FlagToString( mask = PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION, equals = PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION, name = "STATUS_FORCE_SHOW_NAVIGATION"), diff --git a/core/java/android/view/WindowManagerPolicyConstants.java b/core/java/android/view/WindowManagerPolicyConstants.java index 7668d80d3cb1..81c934dffa47 100644 --- a/core/java/android/view/WindowManagerPolicyConstants.java +++ b/core/java/android/view/WindowManagerPolicyConstants.java @@ -16,6 +16,9 @@ package android.view; +import static android.os.IInputConstants.POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY; +import static android.os.IInputConstants.POLICY_FLAG_INPUTFILTER_TRUSTED; + import android.annotation.IntDef; import android.os.PowerManager; @@ -27,10 +30,13 @@ import java.lang.annotation.RetentionPolicy; * @hide */ public interface WindowManagerPolicyConstants { - // Policy flags. These flags are also defined in frameworks/base/include/ui/Input.h. + // Policy flags. These flags are also defined in frameworks/base/include/ui/Input.h and + // frameworks/native/libs/input/android/os/IInputConstants.aidl int FLAG_WAKE = 0x00000001; int FLAG_VIRTUAL = 0x00000002; + int FLAG_INPUTFILTER_TRUSTED = POLICY_FLAG_INPUTFILTER_TRUSTED; + int FLAG_INJECTED_FROM_ACCESSIBILITY = POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY; int FLAG_INJECTED = 0x01000000; int FLAG_TRUSTED = 0x02000000; int FLAG_FILTERED = 0x04000000; diff --git a/core/java/android/view/contentcapture/ContentCaptureEvent.java b/core/java/android/view/contentcapture/ContentCaptureEvent.java index ac4554134a44..10ae69118f54 100644 --- a/core/java/android/view/contentcapture/ContentCaptureEvent.java +++ b/core/java/android/view/contentcapture/ContentCaptureEvent.java @@ -16,6 +16,7 @@ package android.view.contentcapture; import static android.view.contentcapture.ContentCaptureHelper.getSanitizedString; +import static android.view.contentcapture.ContentCaptureManager.DEBUG; import static android.view.contentcapture.ContentCaptureManager.NO_SESSION_ID; import android.annotation.IntDef; @@ -25,8 +26,12 @@ import android.annotation.SystemApi; import android.graphics.Insets; import android.os.Parcel; import android.os.Parcelable; +import android.text.Selection; +import android.text.Spannable; +import android.text.SpannableString; import android.util.Log; import android.view.autofill.AutofillId; +import android.view.inputmethod.BaseInputConnection; import com.android.internal.util.Preconditions; @@ -132,6 +137,9 @@ public final class ContentCaptureEvent implements Parcelable { @Retention(RetentionPolicy.SOURCE) public @interface EventType{} + /** @hide */ + public static final int MAX_INVALID_VALUE = -1; + private final int mSessionId; private final int mType; private final long mEventTime; @@ -143,6 +151,11 @@ public final class ContentCaptureEvent implements Parcelable { private @Nullable ContentCaptureContext mClientContext; private @Nullable Insets mInsets; + private int mComposingStart = MAX_INVALID_VALUE; + private int mComposingEnd = MAX_INVALID_VALUE; + private int mSelectionStartIndex = MAX_INVALID_VALUE; + private int mSelectionEndIndex = MAX_INVALID_VALUE; + /** Only used in the main Content Capture session, no need to parcel */ private boolean mTextHasComposingSpan; @@ -246,19 +259,75 @@ public final class ContentCaptureEvent implements Parcelable { /** @hide */ @NonNull - public ContentCaptureEvent setText(@Nullable CharSequence text, boolean hasComposingSpan) { + public ContentCaptureEvent setText(@Nullable CharSequence text) { mText = text; - mTextHasComposingSpan = hasComposingSpan; return this; } - /** - * The value is not parcelled, become false after parcelled. - * @hide - */ + /** @hide */ + @NonNull + public ContentCaptureEvent setComposingIndex(int start, int end) { + mComposingStart = start; + mComposingEnd = end; + return this; + } + + /** @hide */ + @NonNull + public boolean hasComposingSpan() { + return mComposingStart > MAX_INVALID_VALUE; + } + + /** @hide */ @NonNull - public boolean getTextHasComposingSpan() { - return mTextHasComposingSpan; + public ContentCaptureEvent setSelectionIndex(int start, int end) { + mSelectionStartIndex = start; + mSelectionEndIndex = end; + return this; + } + + private int getComposingStart() { + return mComposingStart; + } + + private int getComposingEnd() { + return mComposingEnd; + } + + private int getSelectionStart() { + return mSelectionStartIndex; + } + + private int getSelectionEnd() { + return mSelectionEndIndex; + } + + private void restoreComposingSpan() { + if (mComposingStart <= MAX_INVALID_VALUE + || mComposingEnd <= MAX_INVALID_VALUE) { + return; + } + if (mText instanceof Spannable) { + BaseInputConnection.setComposingSpans((Spannable) mText, mComposingStart, + mComposingEnd); + } else { + Log.w(TAG, "Text is not a Spannable."); + } + } + + private void restoreSelectionSpans() { + if (mSelectionStartIndex <= MAX_INVALID_VALUE + || mSelectionEndIndex <= MAX_INVALID_VALUE) { + return; + } + + if (mText instanceof SpannableString) { + SpannableString ss = (SpannableString) mText; + ss.setSpan(Selection.SELECTION_START, mSelectionStartIndex, mSelectionStartIndex, 0); + ss.setSpan(Selection.SELECTION_END, mSelectionEndIndex, mSelectionEndIndex, 0); + } else { + Log.w(TAG, "Text is not a SpannableString."); + } } /** @hide */ @@ -374,7 +443,9 @@ public final class ContentCaptureEvent implements Parcelable { throw new IllegalArgumentException("mergeEvent(): got " + "TYPE_VIEW_DISAPPEARED event with neither id or ids: " + event); } else if (eventType == TYPE_VIEW_TEXT_CHANGED) { - setText(event.getText(), event.getTextHasComposingSpan()); + setText(event.getText()); + setComposingIndex(event.getComposingStart(), event.getComposingEnd()); + setSelectionIndex(event.getSelectionStart(), event.getSelectionEnd()); } else { Log.e(TAG, "mergeEvent(" + getTypeAsString(eventType) + ") does not support this event type."); @@ -409,6 +480,14 @@ public final class ContentCaptureEvent implements Parcelable { if (mInsets != null) { pw.print(", insets="); pw.println(mInsets); } + if (mComposingStart > MAX_INVALID_VALUE) { + pw.print(", composing("); pw.print(mComposingStart); + pw.print(", "); pw.print(mComposingEnd); pw.print(")"); + } + if (mSelectionStartIndex > MAX_INVALID_VALUE) { + pw.print(", selection("); pw.print(mSelectionStartIndex); + pw.print(", "); pw.print(mSelectionEndIndex); pw.print(")"); + } } @NonNull @@ -431,11 +510,13 @@ public final class ContentCaptureEvent implements Parcelable { string.append(", class=").append(className); string.append(", id=").append(mNode.getAutofillId()); if (mNode.getText() != null) { - string.append(", text=").append(getSanitizedString(mNode.getText())); + string.append(", text=") + .append(DEBUG ? mNode.getText() : getSanitizedString(mNode.getText())); } } if (mText != null) { - string.append(", text=").append(getSanitizedString(mText)); + string.append(", text=") + .append(DEBUG ? mText : getSanitizedString(mText)); } if (mClientContext != null) { string.append(", context=").append(mClientContext); @@ -443,6 +524,15 @@ public final class ContentCaptureEvent implements Parcelable { if (mInsets != null) { string.append(", insets=").append(mInsets); } + if (mComposingStart > MAX_INVALID_VALUE) { + string.append(", composing=[") + .append(mComposingStart).append(",").append(mComposingEnd).append("]"); + } + if (mSelectionStartIndex > MAX_INVALID_VALUE) { + string.append(", selection=[") + .append(mSelectionStartIndex).append(",") + .append(mSelectionEndIndex).append("]"); + } return string.append(']').toString(); } @@ -469,6 +559,12 @@ public final class ContentCaptureEvent implements Parcelable { if (mType == TYPE_VIEW_INSETS_CHANGED) { parcel.writeParcelable(mInsets, flags); } + if (mType == TYPE_VIEW_TEXT_CHANGED) { + parcel.writeInt(mComposingStart); + parcel.writeInt(mComposingEnd); + parcel.writeInt(mSelectionStartIndex); + parcel.writeInt(mSelectionEndIndex); + } } public static final @android.annotation.NonNull Parcelable.Creator<ContentCaptureEvent> CREATOR = @@ -493,7 +589,7 @@ public final class ContentCaptureEvent implements Parcelable { if (node != null) { event.setViewNode(node); } - event.setText(parcel.readCharSequence(), false); + event.setText(parcel.readCharSequence()); if (type == TYPE_SESSION_STARTED || type == TYPE_SESSION_FINISHED) { event.setParentSessionId(parcel.readInt()); } @@ -503,6 +599,12 @@ public final class ContentCaptureEvent implements Parcelable { if (type == TYPE_VIEW_INSETS_CHANGED) { event.setInsets(parcel.readParcelable(null)); } + if (type == TYPE_VIEW_TEXT_CHANGED) { + event.setComposingIndex(parcel.readInt(), parcel.readInt()); + event.restoreComposingSpan(); + event.setSelectionIndex(parcel.readInt(), parcel.readInt()); + event.restoreSelectionSpans(); + } return event; } diff --git a/core/java/android/view/contentcapture/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java index ed840ce3061b..9241c3074ddd 100644 --- a/core/java/android/view/contentcapture/ContentCaptureManager.java +++ b/core/java/android/view/contentcapture/ContentCaptureManager.java @@ -212,6 +212,9 @@ public final class ContentCaptureManager { private static final String TAG = ContentCaptureManager.class.getSimpleName(); + /** @hide */ + public static final boolean DEBUG = false; + /** Error happened during the data sharing session. */ public static final int DATA_SHARE_ERROR_UNKNOWN = 1; diff --git a/core/java/android/view/contentcapture/MainContentCaptureSession.java b/core/java/android/view/contentcapture/MainContentCaptureSession.java index ad4ba76a17cb..d8ac779ddc27 100644 --- a/core/java/android/view/contentcapture/MainContentCaptureSession.java +++ b/core/java/android/view/contentcapture/MainContentCaptureSession.java @@ -43,9 +43,11 @@ import android.os.Handler; import android.os.IBinder; import android.os.IBinder.DeathRecipient; import android.os.RemoteException; +import android.text.Selection; 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 +62,6 @@ import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; /** @@ -151,12 +152,6 @@ public final class MainContentCaptureSession extends ContentCaptureSession { 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 +347,34 @@ public final class MainContentCaptureSession extends ContentCaptureSession { // 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; - } + final boolean hasComposingSpan = event.hasComposingSpan(); + if (hasComposingSpan) { + 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.hasComposingSpan()) { + 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 +575,6 @@ public final class MainContentCaptureSession extends ContentCaptureSession { ? Collections.EMPTY_LIST : new ArrayList<>(mEvents); mEvents.clear(); - mLastComposingSpan.clear(); return new ParceledListSlice<>(events); } @@ -717,13 +705,35 @@ public final class MainContentCaptureSession extends ContentCaptureSession { // 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 boolean textHasComposingSpan = - text instanceof Spannable && BaseInputConnection.getComposingSpanStart( - (Spannable) text) >= 0; + final CharSequence eventText = stringOrSpannedStringWithoutNoCopySpans(text); + + final int composingStart; + final int composingEnd; + if (text instanceof Spannable) { + composingStart = BaseInputConnection.getComposingSpanStart((Spannable) text); + composingEnd = BaseInputConnection.getComposingSpanEnd((Spannable) text); + } else { + composingStart = ContentCaptureEvent.MAX_INVALID_VALUE; + composingEnd = ContentCaptureEvent.MAX_INVALID_VALUE; + } + + final int startIndex = Selection.getSelectionStart(text); + final int endIndex = Selection.getSelectionEnd(text); mHandler.post(() -> sendEvent( new ContentCaptureEvent(sessionId, TYPE_VIEW_TEXT_CHANGED) - .setAutofillId(id).setText(eventText, textHasComposingSpan))); + .setAutofillId(id).setText(eventText) + .setComposingIndex(composingStart, composingEnd) + .setSelectionIndex(startIndex, endIndex))); + } + + 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 */ diff --git a/core/java/android/view/translation/UiTranslationController.java b/core/java/android/view/translation/UiTranslationController.java index 790b93a1f495..5ac878d88100 100644 --- a/core/java/android/view/translation/UiTranslationController.java +++ b/core/java/android/view/translation/UiTranslationController.java @@ -155,6 +155,7 @@ public class UiTranslationController { destroyTranslators(); runForEachView((view, callback) -> { callback.onClearTranslation(view); + view.clearViewTranslationResponse(); if (view.hasTranslationTransientState()) { view.setHasTransientState(false); view.setHasTranslationTransientState(false); diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java index 25c84ba9d440..8a044fd06dd5 100644 --- a/core/java/android/widget/RemoteViews.java +++ b/core/java/android/widget/RemoteViews.java @@ -114,6 +114,7 @@ import java.lang.invoke.MethodHandle; 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 @@ public class RemoteViews implements Parcelable, Filter { 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 @@ public class RemoteViews implements Parcelable, Filter { } } + @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/Toast.java b/core/java/android/widget/Toast.java index b35eb065e3fb..862829bf9b55 100644 --- a/core/java/android/widget/Toast.java +++ b/core/java/android/widget/Toast.java @@ -71,6 +71,9 @@ import java.util.List; * 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 0f2a3ca6936b..eccff0692fab 100644 --- a/core/java/android/widget/ToastPresenter.java +++ b/core/java/android/widget/ToastPresenter.java @@ -69,7 +69,7 @@ public class ToastPresenter { 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 @@ public class ToastPresenter { 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 @@ public class ToastPresenter { * 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 @@ public class ToastPresenter { 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/ITaskOrganizer.aidl b/core/java/android/window/ITaskOrganizer.aidl index 3eb35c2c5e8a..8b8dba89ea67 100644 --- a/core/java/android/window/ITaskOrganizer.aidl +++ b/core/java/android/window/ITaskOrganizer.aidl @@ -52,6 +52,11 @@ oneway interface ITaskOrganizer { void copySplashScreenView(int taskId); /** + * Called when the Task removed the splash screen. + */ + void onAppSplashScreenViewRemoved(int taskId); + + /** * A callback when the Task is available for the registered organizer. The client is responsible * for releasing the SurfaceControl in the callback. For non-root tasks, the leash may initially * be hidden so it is up to the organizer to show this task. diff --git a/core/java/android/window/SplashScreenView.java b/core/java/android/window/SplashScreenView.java index 000dfb2bfa59..4a3bf91645f2 100644 --- a/core/java/android/window/SplashScreenView.java +++ b/core/java/android/window/SplashScreenView.java @@ -34,8 +34,10 @@ import android.graphics.PixelFormat; import android.graphics.Rect; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; +import android.os.Build; import android.os.Parcel; import android.os.Parcelable; +import android.os.RemoteCallback; import android.os.Trace; import android.util.AttributeSet; import android.util.Log; @@ -76,7 +78,7 @@ import java.time.Instant; */ public final class SplashScreenView extends FrameLayout { private static final String TAG = SplashScreenView.class.getSimpleName(); - private static final boolean DEBUG = false; + private static final boolean DEBUG = Build.IS_DEBUGGABLE; private static final int LIGHT_BARS_MASK = WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS @@ -85,7 +87,7 @@ public final class SplashScreenView extends FrameLayout { | FLAG_TRANSLUCENT_NAVIGATION | FLAG_TRANSLUCENT_STATUS; private boolean mNotCopyable; - private boolean mRevealAnimationSupported = true; + private boolean mIsCopied; private int mInitBackgroundColor; private int mInitIconBackgroundColor; private View mIconView; @@ -104,6 +106,10 @@ public final class SplashScreenView extends FrameLayout { private SurfaceControlViewHost.SurfacePackage mSurfacePackage; @Nullable private SurfaceView mSurfaceView; + @Nullable + private SurfaceControlViewHost mSurfaceHost; + @Nullable + private RemoteCallback mClientCallback; // cache original window and status private Window mWindow; @@ -128,6 +134,7 @@ public final class SplashScreenView extends FrameLayout { private Bitmap mParceledIconBitmap; private Drawable mIconDrawable; private SurfaceControlViewHost.SurfacePackage mSurfacePackage; + private RemoteCallback mClientCallback; private int mBrandingImageWidth; private int mBrandingImageHeight; private Drawable mBrandingDrawable; @@ -162,6 +169,7 @@ public final class SplashScreenView extends FrameLayout { } mIconAnimationStart = Instant.ofEpochMilli(parcelable.mIconAnimationStartMillis); mIconAnimationDuration = Duration.ofMillis(parcelable.mIconAnimationDurationMillis); + mClientCallback = parcelable.mClientCallback; if (DEBUG) { Log.d(TAG, String.format("Building from parcel drawable: %s", mIconDrawable)); } @@ -229,6 +237,7 @@ public final class SplashScreenView extends FrameLayout { view.mInitBackgroundColor = mBackgroundColor; view.mInitIconBackgroundColor = mIconBackground; view.setBackgroundColor(mBackgroundColor); + view.mClientCallback = mClientCallback; view.mBrandingImageView = view.findViewById(R.id.splashscreen_branding_view); @@ -286,7 +295,8 @@ public final class SplashScreenView extends FrameLayout { if (mSurfacePackage == null) { if (DEBUG) { Log.d(TAG, - "Creating Original SurfacePackage. SurfaceView: " + surfaceView); + "SurfaceControlViewHost created on thread " + + Thread.currentThread().getId()); } SurfaceControlViewHost viewHost = new SurfaceControlViewHost(mContext, @@ -298,6 +308,7 @@ public final class SplashScreenView extends FrameLayout { SurfaceControlViewHost.SurfacePackage surfacePackage = viewHost.getSurfacePackage(); surfaceView.setChildSurfacePackage(surfacePackage); view.mSurfacePackage = surfacePackage; + view.mSurfaceHost = viewHost; view.mSurfacePackageCopy = new SurfaceControlViewHost.SurfacePackage( surfacePackage); } else { @@ -353,30 +364,12 @@ public final class SplashScreenView extends FrameLayout { } /** - * 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 */ public void onCopied() { + mIsCopied = true; if (mSurfaceView == null) { return; } @@ -389,6 +382,12 @@ public final class SplashScreenView extends FrameLayout { mSurfacePackage = null; } + /** @hide **/ + @Nullable + public SurfaceControlViewHost getSurfaceHost() { + return mSurfaceHost; + } + @Override public void setAlpha(float alpha) { super.setAlpha(alpha); @@ -427,8 +426,7 @@ public final class SplashScreenView extends FrameLayout { if (DEBUG) { mSurfacePackage.getSurfaceControl().addOnReparentListener( (transaction, parent) -> Log.e(TAG, - String.format("SurfacePackage'surface reparented.\n Parent: %s", - parent), new Throwable())); + String.format("SurfacePackage'surface reparented to %s", parent))); Log.d(TAG, "Transferring surface " + mSurfaceView.toString()); } mSurfaceView.setChildSurfacePackage(mSurfacePackage); @@ -486,9 +484,36 @@ public final class SplashScreenView extends FrameLayout { mHasRemoved = true; } + /** @hide **/ + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + releaseAnimationSurfaceHost(); + } + + private void releaseAnimationSurfaceHost() { + if (mSurfaceHost != null && !mIsCopied) { + final SurfaceControlViewHost finalSurfaceHost = mSurfaceHost; + mSurfaceHost = null; + finalSurfaceHost.getView().post(() -> { + if (DEBUG) { + Log.d(TAG, + "Shell removed splash screen." + + " Releasing SurfaceControlViewHost on thread #" + + Thread.currentThread().getId()); + } + finalSurfaceHost.release(); + }); + } else if (mSurfacePackage != null && mSurfaceHost == null) { + mSurfacePackage = null; + mClientCallback.sendResult(null); + } + } + /** * Called when this view is attached to an activity. This also makes SystemUI colors * transparent so the content of splash screen view can draw fully. + * * @hide */ public void attachHostActivityAndSetSystemUIColors(Activity activity, Window window) { @@ -605,6 +630,7 @@ public final class SplashScreenView extends FrameLayout { private long mIconAnimationDurationMillis; private SurfaceControlViewHost.SurfacePackage mSurfacePackage; + private RemoteCallback mClientCallback; public SplashScreenViewParcelable(SplashScreenView view) { mIconSize = view.mIconView.getWidth(); @@ -661,6 +687,7 @@ public final class SplashScreenView extends FrameLayout { mIconAnimationDurationMillis = source.readLong(); mIconBackground = source.readInt(); mSurfacePackage = source.readTypedObject(SurfaceControlViewHost.SurfacePackage.CREATOR); + mClientCallback = source.readTypedObject(RemoteCallback.CREATOR); } @Override @@ -680,6 +707,7 @@ public final class SplashScreenView extends FrameLayout { dest.writeLong(mIconAnimationDurationMillis); dest.writeInt(mIconBackground); dest.writeTypedObject(mSurfacePackage, flags); + dest.writeTypedObject(mClientCallback, flags); } public static final @NonNull Parcelable.Creator<SplashScreenViewParcelable> CREATOR = @@ -717,5 +745,13 @@ public final class SplashScreenView extends FrameLayout { int getIconBackground() { return mIconBackground; } + + /** + * Sets the {@link RemoteCallback} that will be called by the client to notify the shell + * of the removal of the {@link SplashScreenView}. + */ + public void setClientCallback(@NonNull RemoteCallback clientCallback) { + mClientCallback = clientCallback; + } } } diff --git a/core/java/android/window/TaskOrganizer.java b/core/java/android/window/TaskOrganizer.java index 3340cf4fb707..73995491668a 100644 --- a/core/java/android/window/TaskOrganizer.java +++ b/core/java/android/window/TaskOrganizer.java @@ -117,6 +117,16 @@ public class TaskOrganizer extends WindowOrganizer { public void copySplashScreenView(int taskId) {} /** + * Notify the shell ({@link com.android.wm.shell.ShellTaskOrganizer} that the client has + * removed the splash screen view. + * @see com.android.wm.shell.ShellTaskOrganizer#onAppSplashScreenViewRemoved(int) + * @see SplashScreenView#remove() + */ + @BinderThread + public void onAppSplashScreenViewRemoved(int taskId) { + } + + /** * Called when a task with the registered windowing mode can be controlled by this task * organizer. For non-root tasks, the leash may initially be hidden so it is up to the organizer * to show this task. @@ -236,11 +246,16 @@ public class TaskOrganizer extends WindowOrganizer { } @Override - public void copySplashScreenView(int taskId) { + public void copySplashScreenView(int taskId) { mExecutor.execute(() -> TaskOrganizer.this.copySplashScreenView(taskId)); } @Override + public void onAppSplashScreenViewRemoved(int taskId) { + mExecutor.execute(() -> TaskOrganizer.this.onAppSplashScreenViewRemoved(taskId)); + } + + @Override public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash) { mExecutor.execute(() -> TaskOrganizer.this.onTaskAppeared(taskInfo, leash)); } diff --git a/core/java/com/android/internal/app/IHotwordRecognitionStatusCallback.aidl b/core/java/com/android/internal/app/IHotwordRecognitionStatusCallback.aidl index 9bec505c801d..ec99c95a737c 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 @@ oneway interface IHotwordRecognitionStatusCallback { * @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/graphics/palette/CelebiQuantizer.java b/core/java/com/android/internal/graphics/palette/CelebiQuantizer.java index de6bf2044dbc..454fd00a841c 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 @@ package com.android.internal.graphics.palette; 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 index 408cf1fe9193..21a2212d6c77 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 @@ import android.graphics.ColorSpace; * 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 @@ public class LABCentroid implements CentroidProvider { } @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 @@ public class LABCentroid implements CentroidProvider { } @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 bde036349d3b..000000000000 --- 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 ae8858a8107c..000000000000 --- 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 index 5fcfcbab3159..017adeb3ef27 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 @@ package com.android.internal.graphics.palette; 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 000000000000..6b60f61b91f5 --- /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 1d865c2513cf..19ed8d07394e 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 @@ import java.util.Set; * 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 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]); - } +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; - 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); - } - } + 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 = {}; - 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); - } + private Palette mPalette; - if (pixels.length == 0) { - return; + 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; } - predict(maxColors, 0); + mInputPixelToCount = inputPixelToCount; } - /** 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; + @Override + public List<Palette.Swatch> getQuantizedColors() { + return mPalette.getSwatches(); } - /** Create random starting centroids for K-means. */ - public static float[][] randomMeans(int maxColors, int upperBound) { - float[][] means = new float[maxColors][]; + @Override + public void quantize(@NonNull int[] pixels, int maxColors) { + assert (pixels.length > 0); - // 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); + 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; + } + recalculateClusterCenters(maxColors); + } + + List<Palette.Swatch> swatches = new ArrayList<>(); for (int i = 0; i < maxColors; i++) { - means[i] = new Mean(upperBound, random).center; + float[] cluster = mClusters[i]; + int colorInt = mPointProvider.toInt(cluster); + swatches.add(new Palette.Swatch(colorInt, mClusterPopulations[i])); } - return means; + mPalette = Palette.from(swatches); } - @Override - public void quantize(int[] pixels, int maxColors) { + 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]); + } - @Override - public List<Palette.Swatch> getQuantizedColors() { - return mSwatches; + 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]); + } } - private void predict(int maxColors, int iterationsCompleted) { - double[][] centroidDistance = new double[maxColors][maxColors]; + 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[] meanI = mMeans[i].center; - float[] meanJ = mMeans[j].center; - double distance = mCentroidProvider.distance(meanI, meanJ); - centroidDistance[i][j] = distance; - centroidDistance[j][i] = distance; + float distance = mPointProvider.distance(mClusters[i], mClusters[j]); + mDistanceMatrix[j][i] = distance; + mDistanceMatrix[i][j] = distance; } } - // 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]; + if (mIndexMatrix.length != maxColors) { + mIndexMatrix = 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]; + 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++) { - outputRow[j] = findIndex(distancesFromIToAnotherMean, sortedByDistanceAscending[j]); + mIndexMatrix[i][j] = distances.get(j).getIndex(); } - distanceMatrix[i] = outputRow; } + } + + 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); - // 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); + float minimumDistance = previousDistance; + int newClusterIndex = -1; for (int j = 1; j < maxColors; j++) { - int indexOfClusterFromCurrentToJ = distanceMatrix[indexOfCurrentMean][j]; - double distanceBetweenJAndCurrent = - centroidDistance[indexOfCurrentMean][indexOfClusterFromCurrentToJ]; - if (distanceBetweenJAndCurrent >= (4 * minDistance)) { + int t = mIndexMatrix[previousClusterIndex][j]; + if (mDistanceMatrix[previousClusterIndex][t] >= 4 * previousDistance) { + // Triangle inequality proves there's can be no closer center. break; } - double distanceBetweenJAndColor = mCentroidProvider.distance(mMeans[j].center, - color); - if (distanceBetweenJAndColor < minDistance) { - minDistance = distanceBetweenJAndColor; - mMeanIndexByColor.remove(intColor); - mMeanIndexByColor.put(intColor, j); - anyColorMoved = true; + float distance = mPointProvider.distance(point, mClusters[t]); + if (distance < minimumDistance) { + minimumDistance = distance; + newClusterIndex = t; } } - } - - 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)); - } - - 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); + 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; + } - for (MeanBucket bucket : buckets) { - float[] centroid = bucket.getCentroid(); - if (centroid == null) { - continue; - } + 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; - 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--); - } - } - } - } + } + 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; + } + } - 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); - } + private static class Distance { + private final int mIndex; + private final float mDistance; - predict(buckets.size(), iterationsCompleted + 1); + int getIndex() { + return mIndex; } - } + float getDistance() { + return mDistance; + } - private static int findIndex(double[] list, double element) { - for (int i = 0; i < list.length; i++) { - if (list[i] == element) { - return i; - } + Distance(int index, float distance) { + mIndex = index; + mDistance = distance; } - throw new IllegalArgumentException("Element not in list"); } } diff --git a/core/java/com/android/internal/graphics/palette/WuQuantizer.java b/core/java/com/android/internal/graphics/palette/WuQuantizer.java index a2652ea6d5e1..1cd0d721bce4 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. + * + * Prefer `QuantizerCelebi`: coupled with Kmeans, this provides the best-known results for image + * quantization. * - * <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. + * 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; - - private static final int QUANT_SIZE = 33; - private final List<Palette.Swatch> mSwatches = new ArrayList<>(); +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 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; + return mPalette.getSwatches(); } - 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; + @Override + public void quantize(@NonNull int[] pixels, int colorCount) { + assert (pixels.length > 0); + + 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; + } + } else { + constructHistogram(mInputPixelToCount); + createMoments(); + CreateBoxesResult createBoxesResult = createBoxes(colorCount); + mColors = createResult(createBoxesResult.mResultCount); + } + + List<Palette.Swatch> swatches = new ArrayList<>(); + for (int color : mColors) { + swatches.add(new Palette.Swatch(color, 0)); + } + mPalette = Palette.from(swatches); } - private final int mSize; /* image size, in bytes. */ - private int mMaxColors; - private int[] mQadd; - private final int[] mPixels; + @Nullable + public int[] getColors() { + return mColors; + } - 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]; + /** 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; + } - public WuQuantizer(int[] pixels, int maxColorCount) { - if (pixels == null) { - pixels = new int[]{}; - } - this.mPixels = pixels; - this.mSize = pixels.length; + private static int getIndex(int r, int g, int b) { + return (r << 10) + (r << 6) + (g << 5) + r + g + b; } - @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; - - 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(); + 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))); } + } - cube[0].mR0 = cube[0].mG0 = cube[0].mB0 = 0; - cube[0].mR1 = cube[0].mG1 = cube[0].mB1 = QUANT_SIZE - 1; - next = 0; + 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 (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; + areaR[b] += lineR; + areaG[b] += lineG; + areaB[b] += lineB; + area2[b] += line2; + + 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]; + } + } + } + } - 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; + 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; + + int generatedColorCount = 0; + int next = 0; + + 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 { - vv[next] = 0.0f; + volumeVariance[next] = 0.0; i--; } + next = 0; - temp = vv[0]; - for (k = 1; k <= i; ++k) { - if (vv[k] > temp) { - temp = vv[k]; + + double temp = volumeVariance[0]; + for (int k = 1; k <= i; k++) { + if (volumeVariance[k] > temp) { + temp = volumeVariance[k]; next = k; } } - if (temp <= 0.0f) { + generatedColorCount = i + 1; + if (temp <= 0.0) { break; } } - for (k = 0; k < mMaxColors; ++k) { - weight = getVolume(cube[k], mWt); + return new CreateBoxesResult(maxColorCount, generatedColorCount); + } + + 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) { - 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 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; + } - int bitsPerPixel = 0; - while ((1 << bitsPerPixel) < mMaxColors) { - bitsPerPixel++; - } + 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)]; + + int hypotenuse = (dr * dr + dg * dg + db * db); + int volume2 = volume(cube, mWeights); + double variance2 = xx - ((double) hypotenuse / (double) volume2); + return variance2; + } - List<Palette.Swatch> swatches = new ArrayList<>(); - for (int l = 0; l < k; l++) { - int pixel = colors[l]; - if (pixel == 0) { - continue; + 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; } - swatches.add(new Palette.Swatch(pixel, 0)); + cutDirection = Direction.RED; + } else if (maxG >= maxR && maxG >= maxB) { + cutDirection = Direction.GREEN; + } else { + cutDirection = Direction.BLUE; } - mSwatches.clear(); - mSwatches.addAll(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]; - - for (i = 0; i < 256; i++) { - table[i] = i * i; + two.r1 = one.r1; + two.g1 = one.g1; + two.b1 = one.b1; + + switch (cutDirection) { + case RED: + one.r1 = maxRResult.mCutLocation; + two.r0 = one.r1; + two.g0 = one.g0; + two.b0 = one.b0; + break; + case GREEN: + one.g1 = maxGResult.mCutLocation; + two.r0 = one.r0; + two.g0 = one.g1; + two.b0 = one.b0; + break; + case BLUE: + one.b1 = maxBResult.mCutLocation; + two.r0 = one.r0; + two.g0 = one.g0; + two.b0 = one.b1; + break; + default: + throw new IllegalArgumentException("unexpected direction " + cutDirection); } - mQadd = new int[mSize]; + 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); - 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]; - } + return true; } - /* 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]; - - 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; + 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; } - 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]; - - area[b] += line; - area_r[b] += line_r; - area_g[b] += line_g; - area_b[b] += line_b; - 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]; - } + 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 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]); + 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)]); } - /* 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) { + private static int bottom(Box cube, Direction direction, int[] moment) { + switch (direction) { 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]); + 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 (-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]); + 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 (-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]); + 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: - return 0; + throw new IllegalArgumentException("unexpected direction " + direction); } } - 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) { + private static int top(Box cube, Direction direction, int position, int[] moment) { + switch (direction) { 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]); + 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 (mmt[cube.mR1][pos][cube.mB1] - - mmt[cube.mR1][pos][cube.mB0] - - mmt[cube.mR0][pos][cube.mB1] - + mmt[cube.mR0][pos][cube.mB0]); + 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 (mmt[cube.mR1][cube.mG1][pos] - - mmt[cube.mR1][cube.mG0][pos] - - mmt[cube.mR0][cube.mG1][pos] - + mmt[cube.mR0][cube.mG0][pos]); + 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: - return 0; + throw new IllegalArgumentException("unexpected direction " + direction); } } - 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); + private enum Direction { + RED, + GREEN, + BLUE } - /* 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 */ - } - 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; + private static class MaximizeResult { + // < 0 if cut impossible + final int mCutLocation; + final double mMaximum; - if (temp > max) { - max = temp; - cut[0] = i; - } + MaximizeResult(int cut, double max) { + mCutLocation = cut; + mMaximum = max; } - - return max; } - 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; - - whole_r = getVolume(set1, mMr); - whole_g = getVolume(set1, mMg); - whole_b = getVolume(set1, mMb); - whole_w = getVolume(set1, mWt); - - 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); - - 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; - } else { - dir = BLUE; - } - - set2.mR1 = set1.mR1; - set2.mG1 = set1.mG1; - set2.mB1 = set1.mB1; + private static class CreateBoxesResult { + final int mRequestedCount; + final int mResultCount; - switch (dir) { - case RED: - set2.mR0 = set1.mR1 = cutr[0]; - set2.mG0 = set1.mG0; - set2.mB0 = set1.mB0; - break; - case GREEN: - set2.mG0 = set1.mG1 = cutg[0]; - set2.mR0 = set1.mR0; - set2.mB0 = set1.mB0; - break; - case BLUE: - set2.mB0 = set1.mB1 = cutb[0]; - set2.mR0 = set1.mR0; - set2.mG0 = set1.mG0; - break; + CreateBoxesResult(int requestedCount, int resultCount) { + mRequestedCount = requestedCount; + mResultCount = resultCount; } - 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); + } - return true; + 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 28b325b15b9c..aabcd7f82ac7 100644 --- a/core/java/com/android/internal/jank/InteractionJankMonitor.java +++ b/core/java/com/android/internal/jank/InteractionJankMonitor.java @@ -43,6 +43,10 @@ import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_IN import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__NOTIFICATION_SHADE_SWIPE; import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SETTINGS_PAGE_SCROLL; import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_APP_LAUNCH; +import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_APP_LAUNCH_FROM_HISTORY_BUTTON; +import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_APP_LAUNCH_FROM_MEDIA_PLAYER; +import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_APP_LAUNCH_FROM_QS_TILE; +import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_APP_LAUNCH_FROM_SETTINGS_BUTTON; import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_EXPAND_COLLAPSE_LOCK; import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_HEADS_UP_APPEAR; import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_HEADS_UP_DISAPPEAR; @@ -53,6 +57,7 @@ import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_IN import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_ROW_EXPAND; import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_ROW_SWIPE; import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_SCROLL_FLING; +import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__STATUS_BAR_APP_LAUNCH_FROM_CALL_CHIP; import android.annotation.IntDef; import android.annotation.NonNull; @@ -78,6 +83,7 @@ import com.android.internal.util.PerfettoTrigger; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.Locale; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; @@ -152,6 +158,11 @@ public class InteractionJankMonitor { public static final int CUJ_LAUNCHER_APP_LAUNCH_FROM_WIDGET = 27; public static final int CUJ_SETTINGS_PAGE_SCROLL = 28; public static final int CUJ_LOCKSCREEN_UNLOCK_ANIMATION = 29; + public static final int CUJ_SHADE_APP_LAUNCH_FROM_HISTORY_BUTTON = 30; + public static final int CUJ_SHADE_APP_LAUNCH_FROM_MEDIA_PLAYER = 31; + public static final int CUJ_SHADE_APP_LAUNCH_FROM_QS_TILE = 32; + public static final int CUJ_SHADE_APP_LAUNCH_FROM_SETTINGS_BUTTON = 33; + public static final int CUJ_STATUS_BAR_APP_LAUNCH_FROM_CALL_CHIP = 34; private static final int NO_STATSD_LOGGING = -1; @@ -190,6 +201,11 @@ public class InteractionJankMonitor { UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_LAUNCH_FROM_WIDGET, UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SETTINGS_PAGE_SCROLL, UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_UNLOCK_ANIMATION, + UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_APP_LAUNCH_FROM_HISTORY_BUTTON, + UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_APP_LAUNCH_FROM_MEDIA_PLAYER, + UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_APP_LAUNCH_FROM_QS_TILE, + UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_APP_LAUNCH_FROM_SETTINGS_BUTTON, + UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__STATUS_BAR_APP_LAUNCH_FROM_CALL_CHIP, }; private static volatile InteractionJankMonitor sInstance; @@ -239,6 +255,11 @@ public class InteractionJankMonitor { CUJ_LAUNCHER_APP_LAUNCH_FROM_WIDGET, CUJ_SETTINGS_PAGE_SCROLL, CUJ_LOCKSCREEN_UNLOCK_ANIMATION, + CUJ_SHADE_APP_LAUNCH_FROM_HISTORY_BUTTON, + CUJ_SHADE_APP_LAUNCH_FROM_MEDIA_PLAYER, + CUJ_SHADE_APP_LAUNCH_FROM_QS_TILE, + CUJ_SHADE_APP_LAUNCH_FROM_SETTINGS_BUTTON, + CUJ_STATUS_BAR_APP_LAUNCH_FROM_CALL_CHIP, }) @Retention(RetentionPolicy.SOURCE) public @interface CujType { @@ -577,6 +598,16 @@ public class InteractionJankMonitor { return "SETTINGS_PAGE_SCROLL"; case CUJ_LOCKSCREEN_UNLOCK_ANIMATION: return "LOCKSCREEN_UNLOCK_ANIMATION"; + case CUJ_SHADE_APP_LAUNCH_FROM_HISTORY_BUTTON: + return "SHADE_APP_LAUNCH_FROM_HISTORY_BUTTON"; + case CUJ_SHADE_APP_LAUNCH_FROM_MEDIA_PLAYER: + return "SHADE_APP_LAUNCH_FROM_MEDIA_PLAYER"; + case CUJ_SHADE_APP_LAUNCH_FROM_QS_TILE: + return "SHADE_APP_LAUNCH_FROM_QS_TILE"; + case CUJ_SHADE_APP_LAUNCH_FROM_SETTINGS_BUTTON: + return "SHADE_APP_LAUNCH_FROM_SETTINGS_BUTTON"; + case CUJ_STATUS_BAR_APP_LAUNCH_FROM_CALL_CHIP: + return "STATUS_BAR_APP_LAUNCH_FROM_CALL_CHIP"; } return "UNKNOWN"; } @@ -713,7 +744,8 @@ public class InteractionJankMonitor { } 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/os/TEST_MAPPING b/core/java/com/android/internal/os/TEST_MAPPING index 2b22f08652e7..5a5165ddd7e2 100644 --- a/core/java/com/android/internal/os/TEST_MAPPING +++ b/core/java/com/android/internal/os/TEST_MAPPING @@ -14,6 +14,14 @@ }, { "file_patterns": [ + "Battery[^/]*\\.java", + "Kernel[^/]*\\.java", + "[^/]*Power[^/]*\\.java" + ], + "name": "BatteryUsageStatsProtoTests" + }, + { + "file_patterns": [ "BinderDeathDispatcher\\.java" ], "name": "FrameworksCoreTests", @@ -23,7 +31,11 @@ ] }, { - "file_patterns": ["Battery[^/]*\\.java"], + "file_patterns": [ + "Battery[^/]*\\.java", + "Kernel[^/]*\\.java", + "[^/]*Power[^/]*\\.java" + ], "name": "FrameworksServicesTests", "options": [ { "include-filter": "com.android.server.am.BatteryStatsServiceTest" }, diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java index 47341cd154d7..f212fc7d1228 100644 --- a/core/java/com/android/internal/view/BaseIWindow.java +++ b/core/java/com/android/internal/view/BaseIWindow.java @@ -66,12 +66,12 @@ public class BaseIWindow extends IWindow.Stub { } @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/java/com/android/internal/view/inline/InlineTooltipUi.java b/core/java/com/android/internal/view/inline/InlineTooltipUi.java index 5ec8b30d6a7b..25fa678d0507 100644 --- a/core/java/com/android/internal/view/inline/InlineTooltipUi.java +++ b/core/java/com/android/internal/view/inline/InlineTooltipUi.java @@ -213,6 +213,8 @@ public final class InlineTooltipUi extends PopupWindow implements AutoCloseable if (!mShowing) { params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; + params.privateFlags |= + WindowManager.LayoutParams.PRIVATE_FLAG_NOT_MAGNIFIABLE; mContentContainer.addOnLayoutChangeListener(mAnchoredOnLayoutChangeListener); mWm.addView(mContentContainer, params); mShowing = true; diff --git a/core/jni/Android.bp b/core/jni/Android.bp index 99868346f95b..68388d98dbb4 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -232,6 +232,7 @@ cc_library_shared { "libseccomp_policy", "libgrallocusage", "libscrypt_static", + "libstatssocket_lazy", ], shared_libs: [ @@ -295,11 +296,8 @@ cc_library_shared { "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 8f26d356e8e6..3debb3e03483 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -639,6 +639,8 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote, bool p 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 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote, bool p 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/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp index 56814c7eb774..6e2b9cf250c6 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 @@ android_media_AudioSystem_checkAudioFlinger(JNIEnv *env, jobject clazz) 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 @@ android_media_AudioSystem_setSurroundFormatEnabled(JNIEnv *env, jobject thiz, } 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 @@ static const JNINativeMethod gMethods[] = {"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 ce847e8f70c5..e93b00d7b148 100644 --- a/core/jni/android_util_AssetManager.cpp +++ b/core/jni/android_util_AssetManager.cpp @@ -1244,10 +1244,14 @@ static jlong NativeThemeCreate(JNIEnv* /*env*/, jclass /*clazz*/, jlong ptr) { 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 @@ static void NativeThemeApplyStyle(JNIEnv* env, jclass /*clazz*/, jlong ptr, jlon // 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 NativeThemeCopy(JNIEnv* env, jclass /*clazz*/, jlong dst_asset_manag } } -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 @@ static const JNINativeMethod gAssetManagerMethods[] = { // 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 6b6cbea94009..64b8a1a81e69 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 651e6786c460..083a7aa193aa 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 000000000000..69dcdbb0e94c --- /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/layout/floating_popup_menu_button.xml b/core/res/res/layout/floating_popup_menu_button.xml index c419e46349f4..e4c2a34b1af8 100644 --- a/core/res/res/layout/floating_popup_menu_button.xml +++ b/core/res/res/layout/floating_popup_menu_button.xml @@ -51,7 +51,7 @@ android:gravity="center" android:singleLine="true" android:ellipsize="end" - android:fontFamily="sans-serif-medium" + android:fontFamily="@*android:string/config_bodyFontFamily" android:textSize="@dimen/floating_toolbar_text_size" android:textColor="?attr/floatingToolbarForegroundColor" android:background="@null" diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml index ece2dc777575..85de02e4be95 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> diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml index 5bfd8d591dd4..18cc4c67f22f 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> diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml index 77d3e6066100..1d7ce153d4e5 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> @@ -1961,7 +1965,7 @@ <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> @@ -2201,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 5802c4135af1..b1bf980fcbb4 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> diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml index 79043149b907..af66b0bebfe2 100644 --- a/core/res/res/values-az/strings.xml +++ b/core/res/res/values-az/strings.xml @@ -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> @@ -1711,11 +1715,11 @@ <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="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> @@ -1937,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> @@ -2005,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> @@ -2277,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 31c0bdc84015..4cc46d9b4176 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> diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml index fcfbc7324c11..142373747c8d 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> @@ -2215,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 8c7c9509b1d6..92e1a86198cc 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> diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml index 3a9d5cb96cf3..2a9ecf66d4e9 100644 --- a/core/res/res/values-bn/strings.xml +++ b/core/res/res/values-bn/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> @@ -2158,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 74ba9da3c36b..f811ac2f4b95 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> diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml index 4099ccbb2f62..19762bfc0de3 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> diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml index 6dbf7d4d1afe..95b2b551d78c 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 c93a26ba07e2..79379f10f2c8 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> @@ -2125,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 a67033fec66e..b8727e879f83 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> @@ -1868,7 +1872,7 @@ <string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string> <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"> @@ -2069,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> @@ -2130,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 a2624a13ef1f..2aa10e597c08 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 f16e2e4ce25f..0817cb5d4316 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 2a67834b0cc1..6e3b041f1c2c 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 bb1e6f3dea1a..74973c4e57f1 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 a06053f5c80e..8fe3f42e1672 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 022f06051c55..2d921235a55e 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 000000000000..db438f22208f --- /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 000000000000..db438f22208f --- /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 000000000000..db438f22208f --- /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 000000000000..db438f22208f --- /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 000000000000..db438f22208f --- /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 000000000000..db438f22208f --- /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 000000000000..db438f22208f --- /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 000000000000..db438f22208f --- /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 000000000000..db438f22208f --- /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 a164ffe23f8e..9102b8981869 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 1b6d3d0dd5bd..07f805be51af 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> diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml index b2b0226159c9..937161b88dfd 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> diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml index d9157831fc2b..316013434506 100644 --- a/core/res/res/values-eu/strings.xml +++ b/core/res/res/values-eu/strings.xml @@ -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> diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml index f303be0c25bc..3787d4c9db5f 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> diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml index c1c0349817e7..965970cc9e54 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> diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml index 8abf13370f07..44754d7a9bbf 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> @@ -1975,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 2660df69d04b..cc22d83eb367 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> @@ -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 025bc1d53af3..ba41c75c514a 100644 --- a/core/res/res/values-gl/strings.xml +++ b/core/res/res/values-gl/strings.xml @@ -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> diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml index 0e9d5d5679b5..4157e1fd32eb 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> diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml index d686450a6f3c..6e8bd94f3f1d 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> diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml index c430c4ab39db..98acb8993dbe 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 3d15380196f3..58c38755cf6e 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> diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml index 9b4bb13cc972..860dcf98cc8b 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> diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml index 7dbf5664f59d..b8649c11466c 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> diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml index a15275bc737b..0cf1effb535f 100644 --- a/core/res/res/values-is/strings.xml +++ b/core/res/res/values-is/strings.xml @@ -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> diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml index 3191bd635f83..29dbd76514bc 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> diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml index 1ff6e9dcb9a0..dc43bde6c1c7 100644 --- a/core/res/res/values-iw/strings.xml +++ b/core/res/res/values-iw/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">"לא ניתן להוסיף widget."</string> <string name="ime_action_go" msgid="5536744546326495436">"התחלה"</string> @@ -2225,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 d98974fcc7c9..b282b44197bf 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> @@ -2070,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 1d5661b6fe95..dbc92da44549 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> diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml index 9e72ec87dac5..6d3429e8b770 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> @@ -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> @@ -1976,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> @@ -2157,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 1389104abe3a..19aa889245d3 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> diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml index 470683d06134..a3e0ca57ee0d 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,8 +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> - <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> @@ -1988,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 5474a493c609..4c1691b6ac5f 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> @@ -2157,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 984e6f6a2166..66ec9aa5d42b 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> diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml index 5de05faffdf3..fd83eda7b736 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> diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml index 9a97d9cc9310..ca43ce7ac97d 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 b7d4e0883897..47094a4e2317 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> diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml index 6c9f99d029f6..5a9486e0dc28 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> @@ -2148,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 f468ab008ae2..9ca392a06ace 100644 --- a/core/res/res/values-ml/strings.xml +++ b/core/res/res/values-ml/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-mn/strings.xml b/core/res/res/values-mn/strings.xml index 36165362a2d4..4c01871de148 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> diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml index 69e3c74ea601..1dfa5de9d25a 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> @@ -1976,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> @@ -2117,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 1bab0b216623..2960ca2c0eed 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 23fc7bbb4c9d..2c0ed7ba01df 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> diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml index d24c87933ec4..0ceebf1bab93 100644 --- a/core/res/res/values-nb/strings.xml +++ b/core/res/res/values-nb/strings.xml @@ -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> diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml index 13a17366f0e4..8e7ca7137477 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> @@ -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 4dc2a1b6d3b2..97009396cfaf 100644 --- a/core/res/res/values-nl/strings.xml +++ b/core/res/res/values-nl/strings.xml @@ -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> @@ -1868,7 +1872,7 @@ <string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string> <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 d12bb0b06b43..d6b1e1ee66e8 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> diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml index 1436d47666eb..9a73f9b85245 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 89eb90c8788b..2781df76ea5b 100644 --- a/core/res/res/values-pl/strings.xml +++ b/core/res/res/values-pl/strings.xml @@ -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> diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml index dd899de8a74b..a60cb23b7324 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 378d3b45ce6a..5f1046267317 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 dd899de8a74b..a60cb23b7324 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 953eb72e9c76..dc351a23156a 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> diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml index 4adc5a95ff8b..ea9e292fd9fc 100644 --- a/core/res/res/values-ru/strings.xml +++ b/core/res/res/values-ru/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> diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml index 1bad219e9cd5..60641032538d 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> diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml index ff114cd3e17f..e42cc0116ccf 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> diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml index 658ab8d7b57c..506c066571ac 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> @@ -1914,7 +1918,7 @@ <string name="confirm_battery_saver" msgid="5247976246208245754">"V redu"</string> <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"> @@ -2193,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> @@ -2226,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 ad07eb6cb20a..ed6a6168a841 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> diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml index 4d9dbd6b085c..14f5673c1232 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> diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml index 256c8ac955bc..f5e1f81bdb05 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> diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml index 7780c779372b..c05f866b9d70 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> diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml index f2ada5d4b2d8..9be38c9292a4 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> diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml index 7a363f10f76c..d910224af035 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> @@ -2156,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 9f3f9c374691..b6c6ed5c296a 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> diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml index 4ab94db6281a..4ea1da96a07b 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 6702ce436fa3..306fc8240231 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 96c80fd08e0c..baf4a44a3997 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 3c41e39ca202..83180218325e 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> diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml index 9fee7d85f252..4c30b54b9c02 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> diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml index 7e9c54be5c1d..61aba14d354e 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> diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml index 1198cf634764..7fefe747094d 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 762607064c7e..457f0d518f73 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> diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml index 52ffc605ec63..82be3183f879 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> @@ -2135,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 899cdd7c42d4..85cf88cfb624 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 5ac23365eaee..ee33d48768c5 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -3354,6 +3354,15 @@ (e.g. accessibility, alarms). This is mainly for Wear devices that don't have speakers. --> <bool name="config_allowPriorityVibrationsInLowPowerMode">false</bool> + <!-- The duration (in milliseconds) that should be used to convert vibration ramps to a sequence + of fixed amplitude steps on devices without PWLE support. --> + <integer name="config_vibrationWaveformRampStepDuration">5</integer> + + <!-- The duration (in milliseconds) that should be applied to waveform vibrations that ends in + non-zero amplitudes, . The waveform will + be played as a PWLE instead of on/off calls if this value is set. --> + <integer name="config_vibrationWaveformRampDownDuration">0</integer> + <!-- Number of retries Cell Data should attempt for a given error code before restarting the modem. Error codes not listed will not lead to modem restarts. diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 766ad167e5b3..bdeff89352ea 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 b574415c0a08..7d685a202538 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -2012,6 +2012,8 @@ <java-symbol type="integer" name="config_notificationServiceArchiveSize" /> <java-symbol type="integer" name="config_previousVibrationsDumpLimit" /> <java-symbol type="integer" name="config_defaultVibrationAmplitude" /> + <java-symbol type="integer" name="config_vibrationWaveformRampStepDuration" /> + <java-symbol type="integer" name="config_vibrationWaveformRampDownDuration" /> <java-symbol type="integer" name="config_radioScanningTimeout" /> <java-symbol type="integer" name="config_screenBrightnessSettingMinimum" /> <java-symbol type="integer" name="config_screenBrightnessSettingMaximum" /> diff --git a/core/tests/batterystatstests/BatteryUsageStatsProtoTests/Android.bp b/core/tests/batterystatstests/BatteryUsageStatsProtoTests/Android.bp index 36cb55407d8d..52608351775c 100644 --- a/core/tests/batterystatstests/BatteryUsageStatsProtoTests/Android.bp +++ b/core/tests/batterystatstests/BatteryUsageStatsProtoTests/Android.bp @@ -14,9 +14,11 @@ android_test { 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 333eebb86d4c..7f9d618fc631 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 @@ package com.android.internal.os; 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.Arrays; import java.util.List; - @SmallTest public class BatteryUsageStatsPulledTest { @@ -225,4 +228,75 @@ public class BatteryUsageStatsPulledTest { 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/src/android/os/PackageTagsListTest.java b/core/tests/coretests/src/android/os/PackageTagsListTest.java index 518e02e44b06..9034a5ccdd7f 100644 --- a/core/tests/coretests/src/android/os/PackageTagsListTest.java +++ b/core/tests/coretests/src/android/os/PackageTagsListTest.java @@ -30,6 +30,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import java.util.Arrays; +import java.util.Collections; @Presubmit @RunWith(AndroidJUnit4.class) @@ -40,7 +41,8 @@ public class PackageTagsListTest { PackageTagsList.Builder builder = new PackageTagsList.Builder() .add("package1", "attr1") .add("package1", "attr2") - .add("package2"); + .add("package2") + .add("package4", Arrays.asList("attr1", "attr2")); PackageTagsList list = builder.build(); assertTrue(list.contains(builder.build())); @@ -49,10 +51,13 @@ public class PackageTagsListTest { assertTrue(list.contains("package2", "attr1")); assertTrue(list.contains("package2", "attr2")); assertTrue(list.contains("package2", "attr3")); + assertTrue(list.contains("package4", "attr1")); + assertTrue(list.contains("package4", "attr2")); assertTrue(list.containsAll("package2")); assertTrue(list.includes("package1")); assertTrue(list.includes("package2")); assertFalse(list.contains("package1", "attr3")); + assertFalse(list.contains("package4", "attr3")); assertFalse(list.containsAll("package1")); assertFalse(list.includes("package3")); @@ -92,6 +97,51 @@ public class PackageTagsListTest { } @Test + public void testPackageTagsList_Remove() { + PackageTagsList.Builder builder = new PackageTagsList.Builder() + .add("package1", "attr1") + .add("package1", "attr2") + .add("package2") + .add("package4", Arrays.asList("attr1", "attr2", "attr3")) + .add("package3", "attr1") + .remove("package1", "attr1") + .remove("package1", "attr2") + .remove("package2", "attr1") + .remove("package4", Arrays.asList("attr1", "attr2")) + .remove("package3"); + PackageTagsList list = builder.build(); + + assertTrue(list.contains(builder.build())); + assertFalse(list.contains("package1", "attr1")); + assertFalse(list.contains("package1", "attr2")); + assertTrue(list.contains("package2", "attr1")); + assertTrue(list.contains("package2", "attr2")); + assertTrue(list.contains("package2", "attr3")); + assertFalse(list.contains("package3", "attr1")); + assertFalse(list.contains("package4", "attr1")); + assertFalse(list.contains("package4", "attr2")); + assertTrue(list.contains("package4", "attr3")); + assertTrue(list.containsAll("package2")); + assertFalse(list.includes("package1")); + assertTrue(list.includes("package2")); + assertFalse(list.includes("package3")); + assertTrue(list.includes("package4")); + } + + @Test + public void testPackageTagsList_EmptyCollections() { + PackageTagsList.Builder builder = new PackageTagsList.Builder() + .add("package1", Collections.emptyList()) + .add("package2") + .remove("package2", Collections.emptyList()); + PackageTagsList list = builder.build(); + + assertTrue(list.contains(builder.build())); + assertFalse(list.contains("package1", "attr1")); + assertTrue(list.contains("package2", "attr2")); + } + + @Test public void testWriteToParcel() { PackageTagsList list = new PackageTagsList.Builder() .add("package1", "attr1") diff --git a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureEventTest.java b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureEventTest.java index e6a25d00ff10..f28ee46fdf75 100644 --- a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureEventTest.java +++ b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureEventTest.java @@ -236,13 +236,13 @@ public class ContentCaptureEventTest { @Test public void testMergeEvent_typeViewTextChanged() { final ContentCaptureEvent event = new ContentCaptureEvent(42, TYPE_VIEW_TEXT_CHANGED) - .setText("test", false); + .setText("test"); final ContentCaptureEvent event2 = new ContentCaptureEvent(43, TYPE_VIEW_TEXT_CHANGED) - .setText("empty", true); + .setText("composing").setComposingIndex(0, 1); event.mergeEvent(event2); assertThat(event.getText()).isEqualTo(event2.getText()); - assertThat(event.getTextHasComposingSpan()).isEqualTo(event2.getTextHasComposingSpan()); + assertThat(event.hasComposingSpan()).isEqualTo(event2.hasComposingSpan()); } @Test @@ -283,18 +283,18 @@ public class ContentCaptureEventTest { @Test public void testMergeEvent_differentEventTypes() { final ContentCaptureEvent event = new ContentCaptureEvent(42, TYPE_VIEW_DISAPPEARED) - .setText("test", false).setAutofillId(new AutofillId(1)); + .setText("test").setAutofillId(new AutofillId(1)); final ContentCaptureEvent event2 = new ContentCaptureEvent(17, TYPE_VIEW_TEXT_CHANGED) - .setText("empty", true).setAutofillId(new AutofillId(2)); + .setText("composing").setAutofillId(new AutofillId(2)).setComposingIndex(0, 1); event.mergeEvent(event2); assertThat(event.getText()).isEqualTo("test"); - assertThat(event.getTextHasComposingSpan()).isFalse(); + assertThat(event.hasComposingSpan()).isFalse(); assertThat(event.getId()).isEqualTo(new AutofillId(1)); event2.mergeEvent(event); - assertThat(event2.getText()).isEqualTo("empty"); - assertThat(event2.getTextHasComposingSpan()).isTrue(); + assertThat(event2.getText()).isEqualTo("composing"); + assertThat(event2.hasComposingSpan()).isTrue(); assertThat(event2.getId()).isEqualTo(new AutofillId(2)); } diff --git a/data/etc/car/com.android.car.cluster.home.xml b/data/etc/car/com.android.car.cluster.home.xml index e1d2b18d7167..a3d0fcffc813 100644 --- a/data/etc/car/com.android.car.cluster.home.xml +++ b/data/etc/car/com.android.car.cluster.home.xml @@ -18,5 +18,6 @@ <privapp-permissions package="com.android.car.cluster.home"> <permission name="android.permission.INTERACT_ACROSS_USERS"/> <permission name="android.car.permission.CAR_INSTRUMENT_CLUSTER_CONTROL"/> + <permission name="android.car.permission.CAR_MONITOR_INPUT"/> </privapp-permissions> </permissions> diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml index 240d0565bddb..04291e3dcc5c 100644 --- a/data/etc/privapp-permissions-platform.xml +++ b/data/etc/privapp-permissions-platform.xml @@ -488,6 +488,7 @@ applications that come with the platform <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" /> diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json index 3c9086dde021..ac5e2d0fcacb 100644 --- a/data/etc/services.core.protolog.json +++ b/data/etc/services.core.protolog.json @@ -961,6 +961,12 @@ "group": "WM_DEBUG_APP_TRANSITIONS", "at": "com\/android\/server\/wm\/AppTransitionController.java" }, + "-1003678883": { + "message": "Cleaning splash screen token=%s", + "level": "VERBOSE", + "group": "WM_DEBUG_STARTING_WINDOW", + "at": "com\/android\/server\/wm\/ActivityRecord.java" + }, "-1003060523": { "message": "Finish needs to pause: %s", "level": "VERBOSE", diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java index 0d8715bfaef2..fe80b5845bf5 100644 --- a/graphics/java/android/graphics/drawable/RippleDrawable.java +++ b/graphics/java/android/graphics/drawable/RippleDrawable.java @@ -331,18 +331,18 @@ public class RippleDrawable extends LayerDrawable { private void setRippleActive(boolean active) { if (mRippleActive != active) { mRippleActive = active; - } - if (mState.mRippleStyle == STYLE_SOLID) { - if (active) { - tryRippleEnter(); - } else { - tryRippleExit(); - } - } else { - if (active) { - startPatternedAnimation(); + if (mState.mRippleStyle == STYLE_SOLID) { + if (active) { + tryRippleEnter(); + } else { + tryRippleExit(); + } } else { - exitPatternedAnimation(); + if (active) { + startPatternedAnimation(); + } else { + exitPatternedAnimation(); + } } } } diff --git a/keystore/java/android/security/GenerateRkpKey.java b/keystore/java/android/security/GenerateRkpKey.java index cc1ec1bada50..a1a7aa85519f 100644 --- a/keystore/java/android/security/GenerateRkpKey.java +++ b/keystore/java/android/security/GenerateRkpKey.java @@ -22,10 +22,6 @@ import android.content.Intent; import android.content.ServiceConnection; import android.os.IBinder; import android.os.RemoteException; -import android.util.Log; - -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; /** * GenerateKey is a helper class to handle interactions between Keystore and the RemoteProvisioner @@ -45,25 +41,14 @@ import java.util.concurrent.TimeUnit; * @hide */ public class GenerateRkpKey { - private static final String TAG = "GenerateRkpKey"; - - private static final int NOTIFY_EMPTY = 0; - private static final int NOTIFY_KEY_GENERATED = 1; - private static final int TIMEOUT_MS = 1000; private IGenerateRkpKeyService mBinder; private Context mContext; - private CountDownLatch mCountDownLatch; private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName className, IBinder service) { mBinder = IGenerateRkpKeyService.Stub.asInterface(service); - mCountDownLatch.countDown(); - } - - @Override public void onBindingDied(ComponentName className) { - mCountDownLatch.countDown(); } @Override @@ -79,51 +64,36 @@ public class GenerateRkpKey { mContext = context; } - private void bindAndSendCommand(int command, int securityLevel) throws RemoteException { + /** + * Fulfills the use case of (2) described in the class documentation. Blocks until the + * RemoteProvisioner application can get new attestation keys signed by the server. + */ + public void notifyEmpty(int securityLevel) throws RemoteException { Intent intent = new Intent(IGenerateRkpKeyService.class.getName()); ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); - if (comp == null) { - throw new RemoteException("Could not resolve GenerateRkpKeyService."); - } intent.setComponent(comp); - mCountDownLatch = new CountDownLatch(1); - if (!mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE)) { - throw new RemoteException("Failed to bind to GenerateRkpKeyService"); - } - try { - mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS); - } catch (InterruptedException e) { - Log.e(TAG, "Interrupted: ", e); + if (comp == null || !mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE)) { + throw new RemoteException("Failed to bind to GenerateKeyService"); } if (mBinder != null) { - switch (command) { - case NOTIFY_EMPTY: - mBinder.generateKey(securityLevel); - break; - case NOTIFY_KEY_GENERATED: - mBinder.notifyKeyGenerated(securityLevel); - break; - default: - Log.e(TAG, "Invalid case for command"); - } - } else { - Log.e(TAG, "Binder object is null; failed to bind to GenerateRkpKeyService."); + mBinder.generateKey(securityLevel); } mContext.unbindService(mConnection); } /** - * Fulfills the use case of (2) described in the class documentation. Blocks until the - * RemoteProvisioner application can get new attestation keys signed by the server. - */ - public void notifyEmpty(int securityLevel) throws RemoteException { - bindAndSendCommand(NOTIFY_EMPTY, securityLevel); - } - - /** - * Fulfills the use case of (1) described in the class documentation. Non blocking call. + * FUlfills the use case of (1) described in the class documentation. Non blocking call. */ public void notifyKeyGenerated(int securityLevel) throws RemoteException { - bindAndSendCommand(NOTIFY_KEY_GENERATED, securityLevel); + Intent intent = new Intent(IGenerateRkpKeyService.class.getName()); + ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); + intent.setComponent(comp); + if (comp == null || !mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE)) { + throw new RemoteException("Failed to bind to GenerateKeyService"); + } + if (mBinder != null) { + mBinder.notifyKeyGenerated(securityLevel); + } + mContext.unbindService(mConnection); } } diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java index c048f3bffc75..dc7f3dda35c0 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java @@ -580,7 +580,7 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato } catch (RemoteException e) { // This is not really an error state, and necessarily does not apply to non RKP // systems or hybrid systems where RKP is not currently turned on. - Log.d(TAG, "Couldn't connect to the RemoteProvisioner backend.", e); + Log.d(TAG, "Couldn't connect to the RemoteProvisioner backend."); } success = true; return new KeyPair(publicKey, publicKey.getPrivateKey()); diff --git a/libs/WindowManager/Shell/res/values-de/strings.xml b/libs/WindowManager/Shell/res/values-de/strings.xml index 0195f3df83a6..c5e79f87ca50 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 23b0ed111add..5949099bd6a3 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 911741322345..eecc9cbbba43 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 34f75dab7a1b..c788a03a5b29 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 ef5ed00b4bda..36700bd81717 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 76e4c735241e..6deb0b892316 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 0738ed261f71..f0bf513e264c 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/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java index f7fb63d9ab98..4b1955e56a6c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java @@ -325,6 +325,13 @@ public class ShellTaskOrganizer extends TaskOrganizer { } @Override + public void onAppSplashScreenViewRemoved(int taskId) { + if (mStartingWindow != null) { + mStartingWindow.onAppSplashScreenViewRemoved(taskId); + } + } + + @Override public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) { synchronized (mLock) { onTaskAppeared(new TaskAppearedInfo(taskInfo, leash)); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java index 8c8a56a773f7..dfd878f63283 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java @@ -368,6 +368,13 @@ public class BubbleController { return; } } + for (Bubble b : mBubbleData.getOverflowBubbles()) { + if (task.taskId == b.getTaskId()) { + promoteBubbleFromOverflow(b); + mBubbleData.setExpanded(true); + return; + } + } } }); @@ -815,7 +822,35 @@ public class BubbleController { setIsBubble(bubble, true /* isBubble */); } - @VisibleForTesting + /** + * Expands and selects the provided bubble as long as it already exists in the stack or the + * overflow. + * + * This is currently only used when opening a bubble via clicking on a conversation widget. + */ + public void expandStackAndSelectBubble(Bubble b) { + if (b == null) { + return; + } + if (mBubbleData.hasBubbleInStackWithKey(b.getKey())) { + // already in the stack + mBubbleData.setSelectedBubble(b); + mBubbleData.setExpanded(true); + } else if (mBubbleData.hasOverflowBubbleWithKey(b.getKey())) { + // promote it out of the overflow + promoteBubbleFromOverflow(b); + } + } + + /** + * Expands and selects a bubble based on the provided {@link BubbleEntry}. If no bubble + * exists for this entry, and it is able to bubble, a new bubble will be created. + * + * This is the method to use when opening a bubble via a notification or in a state where + * the device might not be unlocked. + * + * @param entry the entry to use for the bubble. + */ public void expandStackAndSelectBubble(BubbleEntry entry) { if (mIsStatusBarShade) { mNotifEntryToExpandOnShadeUnlock = null; @@ -1383,6 +1418,21 @@ public class BubbleController { } @Override + public void expandStackAndSelectBubble(Bubble bubble) { + mMainExecutor.execute(() -> { + BubbleController.this.expandStackAndSelectBubble(bubble); + }); + } + + @Override + @Nullable + public Bubble getBubbleWithShortcutId(String shortcutId) { + return mMainExecutor.executeBlockingForResult(() -> { + return BubbleController.this.mBubbleData.getAnyBubbleWithShortcutId(shortcutId); + }, Bubble.class); + } + + @Override public void onTaskbarChanged(Bundle b) { mMainExecutor.execute(() -> { BubbleController.this.onTaskbarChanged(b); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java index 69a741c674db..6f5cfd114688 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java @@ -26,6 +26,7 @@ import android.app.PendingIntent; import android.content.Context; import android.content.LocusId; import android.content.pm.ShortcutInfo; +import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Log; @@ -874,6 +875,34 @@ public class BubbleData { return b; } + /** @return any bubble (in the stack or the overflow) that matches the provided shortcutId. */ + @Nullable + Bubble getAnyBubbleWithShortcutId(String shortcutId) { + if (TextUtils.isEmpty(shortcutId)) { + return null; + } + for (int i = 0; i < mBubbles.size(); i++) { + Bubble bubble = mBubbles.get(i); + String bubbleShortcutId = bubble.getShortcutInfo() != null + ? bubble.getShortcutInfo().getId() + : bubble.getMetadataShortcutId(); + if (shortcutId.equals(bubbleShortcutId)) { + return bubble; + } + } + + for (int i = 0; i < mOverflowBubbles.size(); i++) { + Bubble bubble = mOverflowBubbles.get(i); + String bubbleShortcutId = bubble.getShortcutInfo() != null + ? bubble.getShortcutInfo().getId() + : bubble.getMetadataShortcutId(); + if (shortcutId.equals(bubbleShortcutId)) { + return bubble; + } + } + return null; + } + @VisibleForTesting(visibility = PRIVATE) @Nullable public Bubble getBubbleInStackWithKey(String key) { 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 b674c68b2490..f81f086e598f 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 @@ public class BubbleExpandedView extends LinearLayout { 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/BubbleStackView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java index 8613dcbda872..c71f123459ec 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 @@ -50,7 +50,6 @@ import android.view.View; import android.view.ViewGroup; import android.view.ViewOutlineProvider; import android.view.ViewTreeObserver; -import android.view.WindowInsets; import android.view.accessibility.AccessibilityNodeInfo; import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; import android.widget.FrameLayout; @@ -852,13 +851,6 @@ public class BubbleStackView extends FrameLayout 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 +900,16 @@ public class BubbleStackView extends FrameLayout } }); - // 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() @@ -1029,7 +1017,10 @@ public class BubbleStackView extends FrameLayout removeView(mDismissView); } mDismissView = new DismissView(getContext()); + int elevation = getResources().getDimensionPixelSize(R.dimen.bubble_elevation); + addView(mDismissView); + mDismissView.setElevation(elevation); final ContentResolver contentResolver = getContext().getContentResolver(); final int dismissRadius = Settings.Secure.getInt( @@ -1039,6 +1030,8 @@ public class BubbleStackView extends FrameLayout // MagnetizedObjects. mMagneticTarget = new MagnetizedObject.MagneticTarget( mDismissView.getCircle(), dismissRadius); + + mBubbleContainer.bringToFront(); } // TODO: Create ManageMenuView and move setup / animations there @@ -2465,6 +2458,10 @@ public class BubbleStackView extends FrameLayout } } 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/Bubbles.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java index a93ce01dfc7b..c73b5eebc5c2 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java @@ -118,6 +118,19 @@ public interface Bubbles { */ void expandStackAndSelectBubble(BubbleEntry entry); + /** + * Request the stack expand if needed, then select the specified Bubble as current. + * + * @param bubble the bubble to be selected + */ + void expandStackAndSelectBubble(Bubble bubble); + + /** + * @return a bubble that matches the provided shortcutId, if one exists. + */ + @Nullable + Bubble getBubbleWithShortcutId(String shortcutId); + /** Called for any taskbar changes. */ void onTaskbarChanged(Bundle b); 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 12d55b85fac6..0802fb59a008 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 @@ -529,6 +529,11 @@ public class StackAnimationController extends 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/SystemWindows.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java index 9dabec7a13d0..ef113dc5e10a 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 class SystemWindows { 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 ee2202a48bf2..261ff2f8de83 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 @@ public class LegacySplitScreenController implements DisplayController.OnDisplays 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 49266ce1bb62..c275d50a5d56 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 @@ public class OneHandedController implements RemoteCallable<OneHandedController> "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 @@ public class OneHandedController implements RemoteCallable<OneHandedController> 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/PipSurfaceTransactionHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipSurfaceTransactionHelper.java index 9fa3f69b5f60..728794de0865 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 @@ public class PipSurfaceTransactionHelper { // 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); 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 afd7d2694ad6..6451b94caaba 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 @@ -833,10 +833,14 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, 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 = 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 02451c30d4ef..f6b5889dda28 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 @@ public class PhonePipMenuController implements PipMenuController { 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 604ebc08f42e..c42750d62dd4 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 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, // 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/pip/phone/PipResizeGestureHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java index 32553f97c020..841edef9172f 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java @@ -536,8 +536,9 @@ public class PipResizeGestureHandler { mPipTaskOrganizer.scheduleFinishResizePip(mLastResizeBounds, PipAnimationController.TRANSITION_DIRECTION_USER_RESIZE, callback); } + final float magnetRadiusPercent = (float) mLastResizeBounds.width() / mMinSize.x / 2.f; mPipDismissTargetHandler - .setMagneticFieldRadiusPercent((float) mLastResizeBounds.width() / mMinSize.x); + .setMagneticFieldRadiusPercent(magnetRadiusPercent); mPipUiEventLogger.log( PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_RESIZE); } else { 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 f562c8fc4f85..630c8e7575b2 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 @@ interface IStartingWindowListener { * 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 c303a33afc78..1a365fee3b13 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 @@ public class SplashScreenExitAnimation implements Animator.AnimatorListener { } 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 bf1f9e431c6a..df3fee043419 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 @@ -407,7 +407,6 @@ public class SplashscreenContentDrawer { } if (mEmptyView) { splashScreenView.setNotCopyable(); - splashScreenView.setRevealAnimationSupported(false); } splashScreenView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() { @Override 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 8463da6a0ecb..46db35a6e29f 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 @@ -32,9 +32,10 @@ import android.content.res.Resources; 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.RemoteCallback; import android.os.Trace; import android.os.UserHandle; import android.util.Slog; @@ -42,6 +43,7 @@ import android.util.SparseArray; import android.view.Choreographer; import android.view.Display; import android.view.SurfaceControl; +import android.view.SurfaceControlViewHost; import android.view.View; import android.view.WindowManager; import android.widget.FrameLayout; @@ -107,8 +109,6 @@ public class StartingSurfaceDrawer { 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. */ @@ -123,6 +123,13 @@ public class StartingSurfaceDrawer { private final SparseArray<StartingWindowRecord> mStartingWindowRecords = new SparseArray<>(); + /** + * Records of {@link SurfaceControlViewHost} where the splash screen icon animation is + * rendered and that have not yet been removed by their client. + */ + private final SparseArray<SurfaceControlViewHost> mAnimatedSplashScreenSurfaceHosts = + new SparseArray<>(1); + /** Obtain proper context for showing splash screen on the provided display. */ private Context getDisplayContext(Context context, int displayId) { if (displayId == DEFAULT_DISPLAY) { @@ -326,6 +333,12 @@ public class StartingSurfaceDrawer { } } + 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; @@ -382,25 +395,58 @@ public class StartingSurfaceDrawer { /** * Called when the Task wants to copy the splash screen. - * @param taskId */ public void copySplashScreenView(int taskId) { final StartingWindowRecord preView = mStartingWindowRecords.get(taskId); SplashScreenViewParcelable parcelable; - if (preView != null && preView.mContentView != null - && preView.mContentView.isCopyable()) { - parcelable = new SplashScreenViewParcelable(preView.mContentView); - preView.mContentView.onCopied(); + SplashScreenView splashScreenView = preView != null ? preView.mContentView : null; + if (splashScreenView != null && splashScreenView.isCopyable()) { + parcelable = new SplashScreenViewParcelable(splashScreenView); + parcelable.setClientCallback( + new RemoteCallback((bundle) -> mSplashScreenExecutor.execute( + () -> onAppSplashScreenViewRemoved(taskId, false)))); + splashScreenView.onCopied(); + mAnimatedSplashScreenSurfaceHosts.append(taskId, splashScreenView.getSurfaceHost()); } else { parcelable = null; } if (DEBUG_SPLASH_SCREEN) { Slog.v(TAG, "Copying splash screen window view for task: " + taskId - + " parcelable? " + parcelable); + + " parcelable: " + parcelable); } ActivityTaskManager.getInstance().onSplashScreenViewCopyFinished(taskId, parcelable); } + /** + * Called when the {@link SplashScreenView} is removed from the client Activity view's hierarchy + * or when the Activity is clean up. + * + * @param taskId The Task id on which the splash screen was attached + */ + public void onAppSplashScreenViewRemoved(int taskId) { + onAppSplashScreenViewRemoved(taskId, true /* fromServer */); + } + + /** + * @param fromServer If true, this means the removal was notified by the server. This is only + * used for debugging purposes. + * @see #onAppSplashScreenViewRemoved(int) + */ + private void onAppSplashScreenViewRemoved(int taskId, boolean fromServer) { + SurfaceControlViewHost viewHost = + mAnimatedSplashScreenSurfaceHosts.get(taskId); + if (viewHost == null) { + return; + } + mAnimatedSplashScreenSurfaceHosts.remove(taskId); + if (DEBUG_SPLASH_SCREEN) { + String reason = fromServer ? "Server cleaned up" : "App removed"; + Slog.v(TAG, reason + "the splash screen. Releasing SurfaceControlViewHost for task:" + + taskId); + } + viewHost.getView().post(viewHost::release); + } + protected boolean addWindow(int taskId, IBinder appToken, View view, WindowManager wm, WindowManager.LayoutParams params) { boolean shouldSaveView = true; @@ -445,24 +491,19 @@ public class StartingSurfaceDrawer { 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 cb7afc77a65b..9c1dde925762 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 android.window.TaskSnapshot; 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 @@ public class StartingWindowController implements RemoteCallable<StartingWindowCo 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 @@ public class StartingWindowController implements RemoteCallable<StartingWindowCo * * @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 @@ public class StartingWindowController implements RemoteCallable<StartingWindowCo 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 @@ public class StartingWindowController implements RemoteCallable<StartingWindowCo } 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); }); @@ -149,6 +150,14 @@ public class StartingWindowController implements RemoteCallable<StartingWindowCo } /** + * @see StartingSurfaceDrawer#onAppSplashScreenViewRemoved(int) + */ + public void onAppSplashScreenViewRemoved(int taskId) { + mSplashScreenExecutor.execute( + () -> mStartingSurfaceDrawer.onAppSplashScreenViewRemoved(taskId)); + } + + /** * Called when the content of a task is ready to show, starting window can be removed. */ public void removeStartingWindow(int taskId, SurfaceControl leash, Rect frame, @@ -181,7 +190,7 @@ public class StartingWindowController implements RemoteCallable<StartingWindowCo 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 +239,14 @@ public class StartingWindowController implements RemoteCallable<StartingWindowCo }); } - 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/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp index 3a0153fa3dd8..0cde3d1242c8 100644 --- a/libs/androidfw/AssetManager2.cpp +++ b/libs/androidfw/AssetManager2.cpp @@ -1345,7 +1345,10 @@ uint8_t AssetManager2::GetAssignedPackageId(const LoadedPackage* package) const } 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(AssetManager2* asset_manager) : asset_manager_(asset_manager) { 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]; -}; - -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 { +struct ThemeEntryKeyComparer { + bool operator() (const Theme::Entry& entry, uint32_t attr_res_id) const noexcept { + return entry.attr_res_id < attr_res_id; + } }; +} // namespace base::expected<std::monostate, NullOrIOError> Theme::ApplyStyle(uint32_t resid, bool force) { ATRACE_NAME("Theme::ApplyStyle"); @@ -1387,116 +1382,74 @@ base::expected<std::monostate, NullOrIOError> Theme::ApplyStyle(uint32_t resid, // 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; - } + 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; + } - return AssetManager2::SelectedValue(entry.value.dataType, entry.value.data, entry.cookie, - type_spec_flags, 0U /* resid */, {} /* config */); - } - } + type_spec_flags |= entry_it->type_spec_flags; + if (entry_it->value.dataType == Res_value::TYPE_ATTRIBUTE) { + resid = entry_it->value.data; + continue; } - break; - } while (true); + + 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 @@ base::expected<std::monostate, NullOrIOError> Theme::ResolveAttributeReference( } 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_; - - 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; - } + type_spec_flags_ = source.type_spec_flags_; - // 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 @@ base::expected<std::monostate, IOError> Theme::SetTo(const Theme& o) { // 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 @@ base::expected<std::monostate, IOError> Theme::SetTo(const Theme& o) { } // Reset the data in the destination theme. - for (size_t p = 0; p < packages_.size(); p++) { - if (packages_[p] != nullptr) { - packages_[p].reset(); - } - } - - for (size_t p = 0; p < packages_.size(); p++) { - const Package *package = o.packages_[p].get(); - if (package == nullptr) { - continue; - } - - for (size_t t = 0; t < package->types.size(); t++) { - const ThemeType *type = package->types[t].get(); - if (type == nullptr) { + entries_.clear(); + + 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; + + // 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; - } - - 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; - - // 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; - } - } + 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; + } - // 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; - } + attribute_data = fix_package_id(entry.value.data, value_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()); - } + // 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; + } + } - // 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; - } + // 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; + } - 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; + // 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 @@ base::expected<std::monostate, IOError> Theme::SetTo(const Theme& o) { 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 df3abf63323a..7d01395bbbbc 100644 --- a/libs/androidfw/include/androidfw/AssetManager2.h +++ b/libs/androidfw/include/androidfw/AssetManager2.h @@ -508,13 +508,18 @@ class Theme { // 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 @@ class Theme { 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 f658735da515..77114f273d3d 100644 --- a/libs/androidfw/tests/Theme_test.cpp +++ b/libs/androidfw/tests/Theme_test.cpp @@ -251,6 +251,80 @@ TEST_F(ThemeTest, CopyThemeSameAssetManager) { 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 f11486fe924a..393a20780c79 100644 --- a/libs/androidfw/tests/data/styles/R.h +++ b/libs/androidfw/tests/data/styles/R.h @@ -52,6 +52,7 @@ struct R { 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 06774a8a6005..fe46a3fa90c8 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 Binary files differindex 92e9bf90101e..91cd6546c336 100644 --- a/libs/androidfw/tests/data/styles/styles.apk +++ b/libs/androidfw/tests/data/styles/styles.apk diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp index d8715dbf7646..0a232d6272bd 100644 --- a/libs/hwui/Android.bp +++ b/libs/hwui/Android.bp @@ -87,8 +87,8 @@ cc_defaults { cflags: [ "-Wno-unused-variable", ], - } - } + }, + }, } cc_defaults { @@ -108,7 +108,6 @@ cc_defaults { shared_libs: [ "liblog", "libcutils", - "libstatslog", "libutils", "libEGL", "libGLESv1_CM", @@ -122,12 +121,13 @@ cc_defaults { "libandroidfw", "libcrypto", "libsync", - "libstatspull", - "libstatssocket", ], static_libs: [ "libEGL_blobCache", "libprotoutil", + "libstatslog_hwui", + "libstatspull_lazy", + "libstatssocket_lazy", ], }, host: { @@ -135,8 +135,8 @@ cc_defaults { "libandroidfw", "libutils", ], - } - } + }, + }, } cc_defaults { @@ -220,7 +220,7 @@ filegroup { srcs: [ "apex/java/**/*.java", ], - path: "apex/java" + path: "apex/java", } // ------------------------ @@ -238,7 +238,7 @@ cc_library_headers { windows: { enabled: true, }, - } + }, } cc_defaults { @@ -263,7 +263,7 @@ cc_defaults { "apex/android_region.cpp", ], - header_libs: [ "android_graphics_apex_headers" ], + header_libs: ["android_graphics_apex_headers"], target: { android: { @@ -278,7 +278,7 @@ cc_defaults { srcs: [ "apex/LayoutlibLoader.cpp", ], - } + }, }, } @@ -297,7 +297,7 @@ cc_library_headers { windows: { enabled: true, }, - } + }, } cc_defaults { @@ -370,7 +370,7 @@ cc_defaults { "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 @@ cc_defaults { "libjpeg", ], - static_libs: ["libnativehelper_lazy", "libziparchive_for_incfs"], + static_libs: [ + "libnativehelper_lazy", + "libziparchive_for_incfs", + ], target: { android: { @@ -417,13 +420,13 @@ cc_defaults { "libmediandk", "libnativedisplay", "libnativewindow", - "libstatspull", - "libstatssocket", "libpdfium", ], static_libs: [ "libgif", - "libstatslog", + "libstatslog_hwui", + "libstatspull_lazy", + "libstatssocket_lazy", ], }, host: { @@ -434,10 +437,41 @@ cc_defaults { 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 @@ cc_library_headers { 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 @@ cc_defaults { target: { android: { - header_libs: ["libandroid_headers_private" ], + header_libs: ["libandroid_headers_private"], srcs: [ "hwui/AnimatedImageThread.cpp", @@ -572,8 +606,8 @@ cc_defaults { export_static_lib_headers: [ "libarect", ], - } - } + }, + }, } cc_library { @@ -589,7 +623,7 @@ cc_library { target: { android: { version_script: "libhwui.map.txt", - } + }, }, } @@ -608,10 +642,10 @@ cc_defaults { target: { android: { shared_libs: [ - "libgui", - "libui", - ], - } + "libgui", + "libui", + ], + }, }, srcs: [ "tests/common/scenes/*.cpp", @@ -732,5 +766,5 @@ phony { required: [ "hwuimicro", "hwuimacro", - ] + ], } diff --git a/libs/hwui/JankTracker.cpp b/libs/hwui/JankTracker.cpp index 7702f9bba0e4..dd977c32f531 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 8a8b4181bd94..d8735ce57b65 100644 --- a/libs/hwui/Readback.cpp +++ b/libs/hwui/Readback.cpp @@ -275,6 +275,14 @@ CopyResult Readback::copyLayerInto(DeferredLayerUpdater* deferredLayer, SkBitmap 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 4cb4bd8510ab..da252695dd3b 100644 --- a/libs/hwui/Readback.h +++ b/libs/hwui/Readback.h @@ -50,6 +50,7 @@ public: 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 9a9e6d4b77bd..332f7e6f0eac 100644 --- a/libs/hwui/RenderNode.cpp +++ b/libs/hwui/RenderNode.cpp @@ -306,11 +306,17 @@ void RenderNode::pushStagingPropertiesChanges(TreeInfo& info) { 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 @@ void RenderNode::pushStagingPropertiesChanges(TreeInfo& info) { } } +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 @@ void RenderNode::destroyLayers() { 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 6a0b1aafd7c7..8595b6e5f78a 100644 --- a/libs/hwui/RenderNode.h +++ b/libs/hwui/RenderNode.h @@ -345,6 +345,16 @@ public: 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 @@ private: */ 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 807fb75e097c..43f805d906a5 100644 --- a/libs/hwui/effects/StretchEffect.cpp +++ b/libs/hwui/effects/StretchEffect.cpp @@ -188,7 +188,8 @@ static const float ZERO = 0.f; 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 @@ sk_sp<SkShader> StretchEffect::getShader(float width, float height, 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 64fb2bf7ef18..25777c278a11 100644 --- a/libs/hwui/effects/StretchEffect.h +++ b/libs/hwui/effects/StretchEffect.h @@ -93,8 +93,8 @@ public: */ 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 1591ffabd26a..e32c9115483c 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 @@ static void nativeInit(JNIEnv* env, jobject javaObject) { 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 536f651473a9..87ba3978a780 100644 --- a/libs/hwui/jni/Picture.h +++ b/libs/hwui/jni/Picture.h @@ -38,6 +38,7 @@ class Picture { 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 @@ public: 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 ee7b26058952..d86d9ee56f4c 100644 --- a/libs/hwui/jni/Typeface.cpp +++ b/libs/hwui/jni/Typeface.cpp @@ -204,10 +204,9 @@ static sk_sp<SkData> makeSkDataCached(const std::string& path, bool hasVerity) { 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 @@ static std::function<std::shared_ptr<minikin::MinikinFont>()> readMinikinFontSki 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 4289c455453e..602c32a966d3 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 @@ private: 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 @@ static void android_view_ThreadedRenderer_setPictureCapturedCallbackJNI(JNIEnv* 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 bd3b7c93466c..09be630dc741 100644 --- a/libs/hwui/jni/fonts/Font.cpp +++ b/libs/hwui/jni/fonts/Font.cpp @@ -192,7 +192,7 @@ static jfloat Font_getFontMetrics(JNIEnv* env, jobject, jlong fontHandle, jlong // 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 @@ static jlong Font_getReleaseNativeFontFunc(CRITICAL_JNI_PARAMS) { // 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 @@ static jint Font_getPackedStyle(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) { // 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 d7546d86e4f4..7556af918170 100644 --- a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp +++ b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp @@ -171,17 +171,14 @@ void RenderNodeDrawable::forceDraw(SkCanvas* canvas) const { 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 @@ void RenderNodeDrawable::drawContent(SkCanvas* canvas) const { // 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 @@ void RenderNodeDrawable::drawContent(SkCanvas* canvas) const { 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 @@ void RenderNodeDrawable::drawContent(SkCanvas* canvas) const { 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 @@ void RenderNodeDrawable::drawContent(SkCanvas* canvas) const { // 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 @@ void RenderNodeDrawable::drawContent(SkCanvas* canvas) const { 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/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp index a78cd8316624..9bca4df577c9 100644 --- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp +++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp @@ -75,7 +75,9 @@ bool SkiaOpenGLPipeline::draw(const Frame& frame, const SkRect& screenDirty, con 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 039b0f9a6e9a..5462623e75ff 100644 --- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp +++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp @@ -420,7 +420,7 @@ void SkiaPipeline::endCapture(SkSurface* surface) { 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 @@ void SkiaPipeline::renderFrameImpl(const SkRect& clip, 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 46580358aaf5..bc8a5659dd83 100644 --- a/libs/hwui/pipeline/skia/SkiaPipeline.h +++ b/libs/hwui/pipeline/skia/SkiaPipeline.h @@ -80,6 +80,8 @@ protected: 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 1c58c6a5d440..2dbeb3adfab3 100644 --- a/libs/hwui/pipeline/skia/StretchMask.cpp +++ b/libs/hwui/pipeline/skia/StretchMask.cpp @@ -59,8 +59,7 @@ void StretchMask::draw(GrRecordingContext* context, } 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/CacheManager.cpp b/libs/hwui/renderthread/CacheManager.cpp index 46e806081c0c..ded2b06fb3cf 100644 --- a/libs/hwui/renderthread/CacheManager.cpp +++ b/libs/hwui/renderthread/CacheManager.cpp @@ -210,6 +210,14 @@ void CacheManager::onFrameCompleted() { } } +void CacheManager::performDeferredCleanup(nsecs_t cleanupOlderThanMillis) { + if (mGrContext) { + mGrContext->performDeferredCleanup( + std::chrono::milliseconds(cleanupOlderThanMillis), + /* scratchResourcesOnly */true); + } +} + } /* namespace renderthread */ } /* namespace uirenderer */ } /* namespace android */ diff --git a/libs/hwui/renderthread/CacheManager.h b/libs/hwui/renderthread/CacheManager.h index 713ea990ff23..af82672c6f23 100644 --- a/libs/hwui/renderthread/CacheManager.h +++ b/libs/hwui/renderthread/CacheManager.h @@ -23,6 +23,7 @@ #include <SkSurface.h> #include <utils/String8.h> #include <vector> +#include "utils/TimeUtils.h" namespace android { @@ -53,6 +54,8 @@ public: size_t getBackgroundCacheSize() const { return mBackgroundResourceBytes; } void onFrameCompleted(); + void performDeferredCleanup(nsecs_t cleanupOlderThanMillis); + private: friend class RenderThread; diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index a0d93e928876..8bfc2c14ad7c 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -461,6 +461,7 @@ void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo, int64_t sy } void CanvasContext::stopDrawing() { + cleanupResources(); mRenderThread.removeFrameCallback(this); mAnimationContext->pauseAnimators(); mGenerationID++; @@ -619,10 +620,25 @@ nsecs_t CanvasContext::draw() { } } + cleanupResources(); mRenderThread.cacheManager().onFrameCompleted(); return mCurrentFrameInfo->get(FrameInfoIndex::DequeueBufferDuration); } +void CanvasContext::cleanupResources() { + auto& tracker = mJankTracker.frames(); + auto size = tracker.size(); + auto capacity = tracker.capacity(); + if (size == capacity) { + nsecs_t nowNanos = systemTime(SYSTEM_TIME_MONOTONIC); + nsecs_t frameCompleteNanos = + tracker[0].get(FrameInfoIndex::FrameCompleted); + nsecs_t frameDiffNanos = nowNanos - frameCompleteNanos; + nsecs_t cleanupMillis = ns2ms(std::max(frameDiffNanos, 10_s)); + mRenderThread.cacheManager().performDeferredCleanup(cleanupMillis); + } +} + void CanvasContext::reportMetricsWithPresentTime() { if (mFrameMetricsReporter == nullptr) { return; diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h index 6f90e81e51b0..4bdc2514db8c 100644 --- a/libs/hwui/renderthread/CanvasContext.h +++ b/libs/hwui/renderthread/CanvasContext.h @@ -312,6 +312,7 @@ private: bool mExpectSurfaceStats = false; std::function<void(int64_t, int64_t, int64_t)> mASurfaceTransactionCallback; + void cleanupResources(); }; } /* namespace renderthread */ diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp index ac19a153b6fb..6fd644bfa28e 100644 --- a/libs/hwui/renderthread/RenderProxy.cpp +++ b/libs/hwui/renderthread/RenderProxy.cpp @@ -390,6 +390,17 @@ int RenderProxy::copyHWBitmapInto(Bitmap* hwBitmap, SkBitmap* bitmap) { } } +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 0681dc5e16be..6d80949a4eba 100644 --- a/libs/hwui/renderthread/RenderProxy.h +++ b/libs/hwui/renderthread/RenderProxy.h @@ -136,6 +136,7 @@ public: 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 5a718330d68f..f70149111116 100644 --- a/libs/hwui/renderthread/VulkanManager.cpp +++ b/libs/hwui/renderthread/VulkanManager.cpp @@ -425,27 +425,38 @@ Frame VulkanManager::dequeueNextBuffer(VulkanSurface* surface) { 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); - - 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(); + 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; + + 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 @@ status_t VulkanManager::fenceWait(int fence, GrDirectContext* grContext) { 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 @@ status_t VulkanManager::fenceWait(int fence, GrDirectContext* grContext) { 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 @@ status_t VulkanManager::fenceWait(int fence, GrDirectContext* grContext) { 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/service/GraphicsStatsService.cpp b/libs/hwui/service/GraphicsStatsService.cpp index e4198017aee0..ece59051dae7 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 @@ void GraphicsStatsService::finishDumpInMemory(Dump* dump, AStatsEventList* data, 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/LocationManagerInternal.java b/location/java/android/location/LocationManagerInternal.java index 763835c9cbe2..d59756d02348 100644 --- a/location/java/android/location/LocationManagerInternal.java +++ b/location/java/android/location/LocationManagerInternal.java @@ -16,14 +16,10 @@ package android.location; - import android.annotation.NonNull; import android.annotation.Nullable; import android.location.util.identity.CallerIdentity; - -import com.android.internal.annotations.Immutable; - -import java.util.Set; +import android.os.PackageTagsList; /** * Location manager local system service interface. @@ -43,18 +39,14 @@ public abstract class LocationManagerInternal { } /** - * Interface for getting callbacks when a location provider's location tags change. - * - * @see LocationTagInfo + * Interface for getting callbacks when an app id's location provider package tags change. */ - public interface OnProviderLocationTagsChangeListener { + public interface LocationPackageTagsListener { /** - * Called when the location tags for a provider change. - * - * @param providerLocationTagInfo The tag info for a provider. + * Called when the package tags for a location provider change for a uid. */ - void onLocationTagsChanged(@NonNull LocationTagInfo providerLocationTagInfo); + void onLocationPackageTagsChanged(int uid, @NonNull PackageTagsList packageTagsList); } /** @@ -109,58 +101,9 @@ public abstract class LocationManagerInternal { public abstract @Nullable LocationTime getGnssTimeMillis(); /** - * Sets a listener for changes in the location providers' tags. Passing + * Sets a listener for changes in an app id's location provider package tags. Passing * {@code null} clears the current listener. - * - * @param listener The listener. */ - public abstract void setOnProviderLocationTagsChangeListener( - @Nullable OnProviderLocationTagsChangeListener listener); - - /** - * This class represents the location permission tags used by the location provider - * packages in a given UID. These tags are strictly used for accessing state guarded - * by the location permission(s) by a location provider which are required for the - * provider to fulfill its function as being a location provider. - */ - @Immutable - public static class LocationTagInfo { - private final int mUid; - - @NonNull - private final String mPackageName; - - @Nullable - private final Set<String> mLocationTags; - - public LocationTagInfo(int uid, @NonNull String packageName, - @Nullable Set<String> locationTags) { - mUid = uid; - mPackageName = packageName; - mLocationTags = locationTags; - } - - /** - * @return The UID for which tags are related. - */ - public int getUid() { - return mUid; - } - - /** - * @return The package for which tags are related. - */ - @NonNull - public String getPackageName() { - return mPackageName; - } - - /** - * @return The tags for the package used for location related accesses. - */ - @Nullable - public Set<String> getTags() { - return mLocationTags; - } - } + public abstract void setLocationPackageTagsListener( + @Nullable LocationPackageTagsListener listener); } diff --git a/location/java/android/location/provider/LocationProviderBase.java b/location/java/android/location/provider/LocationProviderBase.java index eada22cd94dc..88a24794411c 100644 --- a/location/java/android/location/provider/LocationProviderBase.java +++ b/location/java/android/location/provider/LocationProviderBase.java @@ -62,6 +62,10 @@ import java.util.Objects; * <p>The service should have an intent filter in place for the location provider it wishes to * implements. Defaults for some providers are specified as constants in this class. * + * <p>Location providers are identified by their UID / package name / attribution tag. Based on this + * identity, location providers may be given some special privileges (such as making special + * requests to other location providers). + * * @hide */ @SystemApi @@ -95,14 +99,14 @@ public abstract class LocationProviderBase { public static final String ACTION_FUSED_PROVIDER = "com.android.location.service.FusedLocationProvider"; - private final String mTag; - private final @Nullable String mAttributionTag; - private final IBinder mBinder; + final String mTag; + final @Nullable String mAttributionTag; + final IBinder mBinder; // write locked on mBinder, read lock is optional depending on atomicity requirements - private @Nullable volatile ILocationProviderManager mManager; - private volatile ProviderProperties mProperties; - private volatile boolean mAllowed; + volatile @Nullable ILocationProviderManager mManager; + volatile ProviderProperties mProperties; + volatile boolean mAllowed; public LocationProviderBase(@NonNull Context context, @NonNull String tag, @NonNull ProviderProperties properties) { diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java index 5f6fc17c38cb..8012f03d84b3 100644 --- a/media/java/android/media/AudioSystem.java +++ b/media/java/android/media/AudioSystem.java @@ -27,6 +27,7 @@ import android.content.pm.PackageManager; 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 @@ public class AudioSystem /** @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/MediaRouter.java b/media/java/android/media/MediaRouter.java index 1a2a1aee0eb3..345d9b27c8a8 100644 --- a/media/java/android/media/MediaRouter.java +++ b/media/java/android/media/MediaRouter.java @@ -696,13 +696,17 @@ public class MediaRouter { @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 @@ public class MediaRouter { } 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 @@ public class MediaRouter { } 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 e2e13b048cf7..be6ff1baadd6 100644 --- a/media/java/android/media/RingtoneManager.java +++ b/media/java/android/media/RingtoneManager.java @@ -521,12 +521,12 @@ public class RingtoneManager { 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 50e0d336f981..6ef074090df8 100644 --- a/media/jni/soundpool/Sound.cpp +++ b/media/jni/soundpool/Sound.cpp @@ -214,7 +214,7 @@ status_t Sound::doLoad() } 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 5597fb5e0e51..a34ac0007886 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 66d57e382cc3..dc07c025e08f 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/PrintSpooler/res/values-az/strings.xml b/packages/PrintSpooler/res/values-az/strings.xml index 887434b4409f..fae4736f29e9 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/IllustrationPreference/AndroidManifest.xml b/packages/SettingsLib/IllustrationPreference/AndroidManifest.xml index 120b0859a70a..73163fca5362 100644 --- a/packages/SettingsLib/IllustrationPreference/AndroidManifest.xml +++ b/packages/SettingsLib/IllustrationPreference/AndroidManifest.xml @@ -18,6 +18,6 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.settingslib.widget"> - <uses-sdk android:minSdkVersion="21" /> + <uses-sdk android:minSdkVersion="28" /> </manifest> 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 55b3115a58a4..000000000000 --- 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 54731f51248b..efcd41c2778b 100644 --- a/packages/SettingsLib/IllustrationPreference/res/layout/illustration_preference.xml +++ b/packages/SettingsLib/IllustrationPreference/res/layout/illustration_preference.xml @@ -20,44 +20,38 @@ android:layout_height="wrap_content" android:layout_width="match_parent" android:background="?android:attr/colorBackground" + android:importantForAccessibility="noHideDescendants" android:gravity="center" android:orientation="horizontal"> - <LinearLayout - android:layout_width="match_parent" - android:layout_height="300dp" + <FrameLayout + android:id="@+id/illustration_frame" + android:layout_width="wrap_content" + android:layout_height="@dimen/settingslib_illustration_height" android:layout_gravity="center" android:gravity="center_vertical" android:padding="@dimen/settingslib_illustration_padding" android:orientation="vertical"> + + <View + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="@drawable/protection_background"/> + <com.airbnb.lottie.LottieAnimationView android:id="@+id/lottie_view" - android:adjustViewBounds="true" - android:maxWidth="412dp" - android:layout_width="wrap_content" + android:layout_width="match_parent" android:layout_height="match_parent" - android:layout_gravity="center" - android:clipToOutline="true" - android:background="@drawable/protection_background" - android:importantForAccessibility="no"/> - </LinearLayout> - - <FrameLayout - android:id="@+id/middleground_layout" - android:layout_width="412dp" - android:layout_height="300dp" - android:padding="@dimen/settingslib_illustration_padding" - android:background="@android:color/transparent" - android:layout_gravity="center" - android:visibility="gone"/> + android:layout_gravity="center" /> - <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 + android:id="@+id/middleground_layout" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="@android:color/transparent" + android:layout_gravity="center" + android:visibility="gone"/> + </FrameLayout> </FrameLayout> diff --git a/packages/SettingsLib/IllustrationPreference/res/values/dimens.xml b/packages/SettingsLib/IllustrationPreference/res/values/dimens.xml index 5e540d3740f9..3f38769973db 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/ColorUtils.java b/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/ColorUtils.java index cd2ddebe6367..07102d55ef7e 100644 --- a/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/ColorUtils.java +++ b/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/ColorUtils.java @@ -39,13 +39,6 @@ import java.util.HashMap; public class ColorUtils { private static HashMap<String, Integer> sSysColors; - static { - sSysColors = new HashMap<>(); - sSysColors.put(".colorAccent", android.R.attr.colorAccent); - sSysColors.put(".colorPrimary", android.R.attr.colorPrimary); - sSysColors.put(".colorPrimaryDark", android.R.attr.colorPrimaryDark); - sSysColors.put(".colorSecondary", android.R.attr.colorSecondary); - } private static HashMap<String, Pair<Integer, Integer>> sFixedColors; static { @@ -110,19 +103,6 @@ public class ColorUtils { * Apply the color of tags to the animation. */ public static void applyDynamicColors(Context context, LottieAnimationView animationView) { - for (String key : sSysColors.keySet()) { - final int color = sSysColors.get(key); - animationView.addValueCallback( - new KeyPath("**", key, "**"), - LottieProperty.COLOR_FILTER, - new SimpleLottieValueCallback<ColorFilter>() { - @Override - public ColorFilter getValue(LottieFrameInfo<ColorFilter> frameInfo) { - return new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN); - } - } - ); - } for (String key : sFixedColors.keySet()) { final Pair<Integer, Integer> fixedColorPair = sFixedColors.get(key); final int color = isDarkMode(context) ? fixedColorPair.second : fixedColorPair.first; 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 7b2a0af269a6..e91dd94c715d 100644 --- a/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/IllustrationPreference.java +++ b/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/IllustrationPreference.java @@ -18,17 +18,15 @@ package com.android.settingslib.widget; 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; +import android.view.ViewGroup.LayoutParams; import android.widget.FrameLayout; import android.widget.ImageView; import androidx.annotation.VisibleForTesting; import androidx.preference.Preference; -import androidx.preference.Preference.OnPreferenceClickListener; import androidx.preference.PreferenceViewHolder; import com.airbnb.lottie.LottieAnimationView; @@ -36,14 +34,14 @@ import com.airbnb.lottie.LottieAnimationView; /** * 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 static final String TAG = "IllustrationPreference"; + + private static final boolean IS_ENABLED_LOTTIE_ADAPTIVE_COLOR = false; private int mAnimationId; - private boolean mIsAnimating; private boolean mIsAutoScale; - private ImageView mPlayButton; private LottieAnimationView mIllustrationView; private View mMiddleGroundView; private FrameLayout mMiddleGroundLayout; @@ -71,42 +69,32 @@ public class IllustrationPreference extends Preference implements OnPreferenceCl Log.w(TAG, "Invalid illustration resource id."); return; } + + // To solve the problem of non-compliant illustrations, we set the frame height + // to 300dp and set the length of the short side of the screen to + // the width of the frame. + final int screenWidth = getContext().getResources().getDisplayMetrics().widthPixels; + final int screenHeight = getContext().getResources().getDisplayMetrics().heightPixels; + final FrameLayout illustrationFrame = (FrameLayout) holder.findViewById( + R.id.illustration_frame); + final LayoutParams lp = (LayoutParams) illustrationFrame.getLayoutParams(); + lp.width = screenWidth < screenHeight ? screenWidth : screenHeight; + illustrationFrame.setLayoutParams(lp); + 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); } if (mMiddleGroundView != null) { enableMiddleGroundView(); } - } - - @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; + if (IS_ENABLED_LOTTIE_ADAPTIVE_COLOR) { + ColorUtils.applyDynamicColors(getContext(), mIllustrationView); + } } @VisibleForTesting @@ -149,6 +137,13 @@ public class IllustrationPreference extends Preference implements OnPreferenceCl mIsAutoScale ? ImageView.ScaleType.CENTER_CROP : ImageView.ScaleType.CENTER_INSIDE); } + /** + * Set the lottie illustration resource id. + */ + public void setLottieAnimationResId(int resId) { + mAnimationId = resId; + } + private void enableMiddleGroundView() { mMiddleGroundLayout.removeAllViews(); mMiddleGroundLayout.addView(mMiddleGroundView); @@ -158,7 +153,6 @@ public class IllustrationPreference extends Preference implements OnPreferenceCl 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 +160,5 @@ public class IllustrationPreference extends Preference implements OnPreferenceCl 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/RadioButtonPreference/res/layout/preference_radio.xml b/packages/SettingsLib/RadioButtonPreference/res/layout/preference_radio.xml index b299061ce591..906ff2cc09d5 100644 --- a/packages/SettingsLib/RadioButtonPreference/res/layout/preference_radio.xml +++ b/packages/SettingsLib/RadioButtonPreference/res/layout/preference_radio.xml @@ -104,7 +104,7 @@ android:gravity="center_vertical"> <View android:layout_width=".75dp" - android:layout_height="match_parent" + android:layout_height="32dp" android:layout_marginTop="16dp" android:layout_marginBottom="16dp" android:background="?android:attr/dividerVertical" /> diff --git a/packages/SettingsLib/SearchWidget/res/values-kk/strings.xml b/packages/SettingsLib/SearchWidget/res/values-kk/strings.xml index 92c45ba7e187..323fa67ce1f3 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 100acd2e917a..f13f4cde496c 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 5683b6ae85d0..0fa4bd3351e2 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 5683b6ae85d0..0fa4bd3351e2 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 000000000000..a4c780bc20de --- /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/values-night-v31/colors.xml b/packages/SettingsLib/SettingsTheme/res/values-night-v31/colors.xml index 426a2ba447f2..69975cd2dad5 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 fcba6bd95cb6..aed6338495f0 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 e3a023995e76..9610c9443184 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 b3378b201f4d..6b18f2879659 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/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml index 6b16a294b8bc..366cb0677e46 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 9943bbb235eb..8a5da977717d 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 8f146e04a0a7..0eef43b18a9a 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 de942a33f6bf..b8796fe107e7 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 6eeef0a581e5..4224e5a93d39 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 aaa8753b6fe0..a5a3321d821b 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 1edd95e5e4da..790323003ba1 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 d20e5daeae31..0fb717898be6 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 d92256d3b98f..4d92282b62d6 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 9c8eff45fc28..b7fdef23ce67 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 46921a4f3262..d3049b13eb93 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 557e917d243b..eab1cd2b71a5 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 2a3b0855669b..7376d7eeaa93 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 d7c5d5571ff7..1dc2d146622b 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 492c6de6bdbf..f092a5198f6c 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 19ccac65b44c..5d4301c2afd3 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 2caa3f78876a..02317eae12e6 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 f307e16fdfa7..f15db49c2af1 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 2caa3f78876a..02317eae12e6 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 2caa3f78876a..02317eae12e6 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 2d2b036d90c7..ce5a6bc780e1 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 3ee5dab48cb3..d050ff874df3 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 d63ea7b26d55..540a47200e46 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 ed698e2de922..f740cc5495a4 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 ebc62f2fd852..06e1abd70e78 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 00a18d363ec4..92e624dcaf71 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 b3187a53ae94..11bcb3a36b06 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 b7851656362f..a622385a652a 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 52c4ec29d914..c4797fc33b7b 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 037a9a972fb7..0d009de170ce 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 6aaa23ef9913..b8d8f3597176 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 b6ac9597776f..8abbfcf74094 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 ac074b0d5d1c..217ff15ef20d 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 3377c456572a..e75b0ddf5b17 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 5f6c1a298958..44b322d0b2da 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 9f7b1f06d3cc..4bb472417c1a 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 c972a996fb5e..b224330064db 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 17b184a7f08c..1d2295c7a47a 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 8e5649fbb6f4..5c894a1bab37 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 62d887daf6b0..3f23c75eaf44 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 f67d2b2521d5..472377196781 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 be176cba4401..baae75b17073 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 7e67b9b2b77f..fdbcba4aa1e7 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 fde4d7251004..21dce27988c6 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 2bedaa2109f4..6e6a5a76d766 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 c6086ad21124..140eb3bb1a30 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 7eea529d5df1..f4962f94a09f 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 79e487037db8..e920b31ea633 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 7f56aad98c17..c43d879a9d2c 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 aee2e6103eb5..81f75c570b45 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 5ff7d1b15814..9583b506cf14 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 a7d621350070..955937b93992 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 667b3399dd62..8ddb2981e3fc 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 1011e330a48c..13788c43bea8 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 e01c123d9d78..dac55c5a5e3b 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 cde30ca98735..769b468df215 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 aaf2c637a225..0bf1a7802a0c 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 806d87b8d89f..ca4308c6c92e 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 8c86031fce79..21bd1ad4a0e8 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 635f0a81ae15..aaa892a4969b 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 7e8a5714a00f..99faea7afc10 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 d6f6da3f8591..021a75e724bb 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 294f61a32365..cdea8b2a4512 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 d6f6da3f8591..021a75e724bb 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 c922684abfb0..e02bada35233 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 24a5039221f5..923917b0eeba 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 ddfa1c5f17bb..3c79bf38ccd8 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 0d04d69c0702..5be0d993e7ce 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 796b9386bfec..07e367bab045 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 99d5c7123a4e..1f30a02eb155 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 9830ddb5f2ab..11adbe529ff4 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 12080222b30f..f4b92afa216e 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 0b49cf57ee33..2625a414ebbf 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 a829ab214c88..612fd700031e 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 83ff62044aca..7f596e301b05 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 f721f1514a2b..3851ccb0c8a2 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 57f01a3c57df..a381c351c98c 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 50679902c5ee..03efe82b0c93 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 061cacea775c..e737c7dc7089 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 6eb3c400bbf4..45e9f4f91a4a 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 ad1a91755254..96b8853dce8f 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 2c4e97f42a4d..4509430f00e9 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 d0cbcd4b1874..3e6b3c2b4afe 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 734a9a5d27ae..42d95b7ffeae 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 17b0a92fe18f..20fa1876ef24 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 3236fd0415ad..f49d3cc9ba2d 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 7ae19707a672..603d09344e2e 100644 --- a/packages/SettingsLib/res/values/strings.xml +++ b/packages/SettingsLib/res/values/strings.xml @@ -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 78a42bef2d7b..849c3d97d731 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 @@ package com.android.settingslib.enterprise; 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 @@ public abstract class ActionDisabledLearnMoreButtonLauncher { 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 @@ public abstract class ActionDisabledLearnMoreButtonLauncher { 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 7014da0df0bf..62582d71f8fb 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.verify; 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 @@ public final class ActionDisabledLearnMoreButtonLauncherTest { private Context mContext; @Mock + private DevicePolicyManager mDevicePolicyManager; + + @Mock private UserManager mUserManager; @Spy @@ -77,6 +81,7 @@ public final class ActionDisabledLearnMoreButtonLauncherTest { 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 @@ public final class ActionDisabledLearnMoreButtonLauncherTest { } @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 @@ public final class ActionDisabledLearnMoreButtonLauncherTest { } @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 @@ public final class ActionDisabledLearnMoreButtonLauncherTest { } @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 @@ public final class ActionDisabledLearnMoreButtonLauncherTest { .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 f197cbb2ac70..89b0fe72ca16 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 @@ package com.android.settingslib.widget; 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 @@ public class IllustrationPreferenceTest { } @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 c9c3db8a2e27..eb8196176034 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 @@ public class GlobalSettings { 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 f538875bf337..3297937e3e75 100644 --- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java +++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java @@ -587,7 +587,6 @@ public class SettingsBackupTest { 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 bcb21d1d64ce..959b5ca56687 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-pa/strings.xml b/packages/Shell/res/values-pa/strings.xml index d0c29055ecc1..daeac3cf0b04 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/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt index 8bc3d228f7a8..2579e7084e08 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt @@ -238,7 +238,9 @@ class ActivityLaunchAnimator( * during the animation. */ @JvmStatic - fun fromView(view: View): Controller = GhostedViewLaunchAnimatorController(view) + fun fromView(view: View, cujType: Int? = null): Controller { + return GhostedViewLaunchAnimatorController(view, cujType) + } } /** diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/GhostedViewLaunchAnimatorController.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/GhostedViewLaunchAnimatorController.kt index 4b655a1a1b02..ffb7ab4eff7c 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/animation/GhostedViewLaunchAnimatorController.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/GhostedViewLaunchAnimatorController.kt @@ -14,6 +14,7 @@ import android.view.View import android.view.ViewGroup import android.view.ViewGroupOverlay import android.widget.FrameLayout +import com.android.internal.jank.InteractionJankMonitor import kotlin.math.min /** @@ -29,7 +30,10 @@ import kotlin.math.min */ open class GhostedViewLaunchAnimatorController( /** The view that will be ghosted and from which the background will be extracted. */ - private val ghostedView: View + private val ghostedView: View, + + /** The [InteractionJankMonitor.CujType] associated to this animation. */ + private val cujType: Int? = null ) : ActivityLaunchAnimator.Controller { /** The container to which we will add the ghost view and expanding background. */ override var launchContainer = ghostedView.rootView as ViewGroup @@ -125,6 +129,8 @@ open class GhostedViewLaunchAnimatorController( val matrix = ghostView?.animationMatrix ?: Matrix.IDENTITY_MATRIX matrix.getValues(initialGhostViewMatrixValues) + + cujType?.let { InteractionJankMonitor.getInstance().begin(ghostedView, it) } } override fun onLaunchAnimationProgress( @@ -167,6 +173,8 @@ open class GhostedViewLaunchAnimatorController( } override fun onLaunchAnimationEnd(isExpandingFullyAbove: Boolean) { + cujType?.let { InteractionJankMonitor.getInstance().end(it) } + backgroundDrawable?.wrapped?.alpha = startBackgroundAlpha GhostView.removeGhost(ghostedView) 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 47a373ebf429..7c81325d685f 100644 --- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ActivityStarter.java +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ActivityStarter.java @@ -87,8 +87,17 @@ public interface ActivityStarter { 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(); + + /** + * Whether running this action when we are locked will start an animation on the keyguard. + */ + default boolean willRunAnimationOnKeyguard() { + return false; + } } } diff --git a/packages/SystemUI/proguard.flags b/packages/SystemUI/proguard.flags index 6c06b0a19844..4adb54686a89 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/values-ml/strings.xml b/packages/SystemUI/res-keyguard/values-ml/strings.xml index 76ee66b82cce..08717675e295 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/drawable/people_space_activity_card.xml b/packages/SystemUI/res/drawable/people_space_activity_card.xml deleted file mode 100644 index 7e2db635702c..000000000000 --- a/packages/SystemUI/res/drawable/people_space_activity_card.xml +++ /dev/null @@ -1,18 +0,0 @@ -<!-- - ~ 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. - --> -<shape xmlns:android="http://schemas.android.com/apk/res/android"> - <solid android:color="@color/people_tile_background" /> -</shape>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/rounded_bg_full_large_radius.xml b/packages/SystemUI/res/drawable/rounded_bg_full_large_radius.xml index aa940bde7e0d..29a014a713f7 100644 --- a/packages/SystemUI/res/drawable/rounded_bg_full_large_radius.xml +++ b/packages/SystemUI/res/drawable/rounded_bg_full_large_radius.xml @@ -14,7 +14,8 @@ limitations under the License. --> <shape xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" android:shape="rectangle"> - <solid android:color="?android:attr/colorBackgroundFloating" /> + <solid android:color="?androidprv:attr/colorAccentPrimary" /> <corners android:radius="40dp" /> </shape> diff --git a/packages/SystemUI/res/drawable/screenshot_border.xml b/packages/SystemUI/res/drawable/screenshot_border.xml index bb858dbc795a..c1accdc7063a 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 5c3c12c572f6..ff5c62e1600b 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 cfd2dc214477..b61b28ed1d9e 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/drawable/volume_row_seekbar_progress.xml b/packages/SystemUI/res/drawable/volume_row_seekbar_progress.xml index 4f97ca47513c..21b177bead11 100644 --- a/packages/SystemUI/res/drawable/volume_row_seekbar_progress.xml +++ b/packages/SystemUI/res/drawable/volume_row_seekbar_progress.xml @@ -32,7 +32,7 @@ android:gravity="center_vertical|right" android:height="@dimen/rounded_slider_icon_size" android:width="@dimen/rounded_slider_icon_size" - android:right="@dimen/rounded_slider_icon_inset"> + android:right="@dimen/volume_slider_icon_inset"> <rotate android:fromDegrees="-270" android:toDegrees="-270"> diff --git a/packages/SystemUI/res/layout/global_screenshot.xml b/packages/SystemUI/res/layout/global_screenshot.xml index 5bd181c82492..93bd58113bc2 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 60dbaf97b7f7..ba46edced03c 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/long_screenshot.xml b/packages/SystemUI/res/layout/long_screenshot.xml index 8e30aecd6a27..3f4baaf27b84 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,8 +97,9 @@ 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" + app:containerBackgroundColor="?android:colorBackgroundFloating" tools:background="?android:colorBackground" tools:minHeight="100dp" tools:minWidth="100dp" /> @@ -128,7 +140,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 9a575893458d..645dba4459a4 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"/> - - <ImageView - android:id="@+id/media_cover2" + 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> + + <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"/> - - <ImageView - android:id="@+id/media_cover3" + 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> + + <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"/> - - <ImageView - android:id="@+id/media_cover4" + 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> + + <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"/> - - <ImageView - android:id="@+id/media_cover5" + 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> + + <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"/> - - <ImageView - android:id="@+id/media_cover6" + 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> + + <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 10bdaaae6634..c341f7393318 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_activity.xml b/packages/SystemUI/res/layout/people_space_activity.xml index fa199439ec69..7102375a89bf 100644 --- a/packages/SystemUI/res/layout/people_space_activity.xml +++ b/packages/SystemUI/res/layout/people_space_activity.xml @@ -15,6 +15,7 @@ --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" android:id="@+id/top_level" android:layout_width="match_parent" android:layout_height="match_parent" @@ -41,7 +42,8 @@ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem" android:textColor="?android:attr/textColorPrimary" android:textSize="16sp" - android:padding="24dp" /> + android:paddingVertical="24dp" + android:paddingHorizontal="48dp"/> <androidx.core.widget.NestedScrollView android:id="@+id/scroll_view" @@ -65,8 +67,8 @@ android:id="@+id/priority_header" android:text="@string/priority_conversations" android:layout_width="wrap_content" - android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem" - android:textColor="?android:attr/colorAccent" + android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Notification.Title" + android:textColor="?androidprv:attr/colorAccentPrimaryVariant" android:textSize="14sp" android:paddingStart="16dp" android:layout_height="wrap_content"/> @@ -92,8 +94,8 @@ android:gravity="start" android:text="@string/recent_conversations" android:layout_width="wrap_content" - android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem" - android:textColor="?android:attr/colorAccent" + android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Notification.Title" + android:textColor="?androidprv:attr/colorAccentPrimaryVariant" android:textSize="14sp" android:paddingStart="16dp" android:layout_height="wrap_content"/> diff --git a/packages/SystemUI/res/layout/people_space_activity_no_conversations.xml b/packages/SystemUI/res/layout/people_space_activity_no_conversations.xml index 232cd7236113..2a4a21f5f1ab 100644 --- a/packages/SystemUI/res/layout/people_space_activity_no_conversations.xml +++ b/packages/SystemUI/res/layout/people_space_activity_no_conversations.xml @@ -55,6 +55,7 @@ android:background="@drawable/rounded_bg_full_large_radius" android:onClick="dismissActivity" android:text="@string/okay" + android:textColor="?android:attr/textColorPrimary" android:layout_marginBottom="60dp" android:layout_alignParentBottom="true" /> diff --git a/packages/SystemUI/res/layout/people_space_initial_layout.xml b/packages/SystemUI/res/layout/people_space_initial_layout.xml index ec29d18d607d..c57ec345ba57 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 abb771b98667..061b0d967652 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_tile_view.xml b/packages/SystemUI/res/layout/people_space_tile_view.xml index 3e901808e66a..2a2c35dde841 100644 --- a/packages/SystemUI/res/layout/people_space_tile_view.xml +++ b/packages/SystemUI/res/layout/people_space_tile_view.xml @@ -13,7 +13,9 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" android:id="@+id/tile_view" android:layout_width="match_parent" android:layout_height="wrap_content" @@ -21,7 +23,7 @@ <LinearLayout android:orientation="vertical" - android:background="@drawable/people_space_activity_card" + android:background="?androidprv:attr/colorSurface" android:padding="12dp" android:elevation="4dp" android:layout_width="match_parent" diff --git a/packages/SystemUI/res/layout/people_space_widget_item.xml b/packages/SystemUI/res/layout/people_space_widget_item.xml index 170386f5ecc5..17d0c561c646 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 2c6acbc4602e..d4a8e15101bd 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 b7e86a3b0b84..3f78fe752609 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 8b2fddc5c927..ebb61c94eca5 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 1086a1361366..0a5bf1d7c49f 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 22fcd3bcce37..553b8a43e033 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 0a9feb819d74..317dbc09eae6 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/qs_tile_label.xml b/packages/SystemUI/res/layout/qs_tile_label.xml index 1d93f5d69da8..536b0423ce16 100644 --- a/packages/SystemUI/res/layout/qs_tile_label.xml +++ b/packages/SystemUI/res/layout/qs_tile_label.xml @@ -33,6 +33,7 @@ android:gravity="start" android:textDirection="locale" android:ellipsize="marquee" + android:marqueeRepeatLimit="1" android:singleLine="true" android:textAppearance="@style/TextAppearance.QS.TileLabel"/> @@ -43,6 +44,7 @@ android:gravity="start" android:textDirection="locale" android:ellipsize="marquee" + android:marqueeRepeatLimit="1" android:singleLine="true" android:visibility="gone" android:textAppearance="@style/TextAppearance.QS.TileLabel.Secondary" diff --git a/packages/SystemUI/res/layout/udfps_view.xml b/packages/SystemUI/res/layout/udfps_view.xml index e5e8fe6ed5dc..687830d5c7b3 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 9b6c92c71e5d..1112bcdbd14d 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 aa997440d102..214937105315 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 3d2e6b2520c5..fe3cc8eaeb06 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 d3401f89d846..83b483e81463 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> @@ -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 5f3e20f5c756..50d866d0ce54 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 853e00fe1ad7..9784d534a163 100644 --- a/packages/SystemUI/res/values-az/strings.xml +++ b/packages/SystemUI/res/values-az/strings.xml @@ -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,7 +339,7 @@ <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> @@ -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> @@ -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> @@ -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 ef524b841273..677bfb2d51a9 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 f1f238c1e8ee..6576a920e302 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 75bc1132fff0..d51bc7b21318 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> diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml index b72381aa9469..b402402e7de4 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 659558969001..cfcceb69f1e2 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 ba3a3f4447a6..925a293b191b 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 11dfe71522b0..f3d64ab56a39 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> @@ -520,7 +520,7 @@ <string name="manage_notifications_text" msgid="6885645344647733116">"Spravovat"</string> <string name="manage_notifications_history_text" msgid="57055985396576230">"Historie"</string> <string name="notification_section_header_incoming" msgid="850925217908095197">"Nové"</string> - <string name="notification_section_header_gentle" msgid="6804099527336337197">"Ticho"</string> + <string name="notification_section_header_gentle" msgid="6804099527336337197">"Tiché"</string> <string name="notification_section_header_alerting" msgid="5581175033680477651">"Oznámení"</string> <string name="notification_section_header_conversations" msgid="821834744538345661">"Konverzace"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Vymazat všechna tichá oznámení"</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 4301f88d73dc..0c7a7439a784 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 8ebfebaf2765..0f18757975fd 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 3b23c35118a3..9525f99d5948 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 8f5bf75bac6c..c346bbe68438 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 d47a4e93795e..b588e861639a 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 8f5bf75bac6c..c346bbe68438 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 8f5bf75bac6c..c346bbe68438 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 79400fe90082..a73c3878eaae 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 94b8d59fee61..051c0ddd687d 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 909dddac80ac..d04fd45b50dd 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> @@ -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 0ff64cb40cb2..00d98c256567 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 d48beba6ab08..78eb7289c786 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,7 +722,7 @@ <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> @@ -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> diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml index 476f6d2ffc6c..10e95f4be3bc 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 805695b0c68e..51b73df555ec 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> @@ -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 6f8eea600440..e657308da857 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 5710c50fe1dc..04f7692c5720 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> diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml index 6230687b273e..52c6e3360cf2 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> @@ -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 adc01b8c4eb9..c06826ba65c4 100644 --- a/packages/SystemUI/res/values-gu/strings.xml +++ b/packages/SystemUI/res/values-gu/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-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml index d73be920fbec..cdead4108f1c 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 fd1592d13d18..14250a774349 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 0fe63af5fa2a..2022281c890e 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 1b48c098360c..4fb191f93035 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> diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml index 1bae009986f7..7e4ba76c340c 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 719c16dd8d14..229bcbb344bd 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 c838ca08a6f5..6c1ef8aa7294 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 a7cdfc1b1d73..aae58cbbce87 100644 --- a/packages/SystemUI/res/values-iw/strings.xml +++ b/packages/SystemUI/res/values-iw/strings.xml @@ -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 ad553988eb42..2ba73b365036 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 fae5977ddf29..1f071a209377 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 bbd4ff23c7d7..9ab5d80b1900 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,9 +742,9 @@ <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> @@ -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 8aeab28abf3e..6ce7300f4a73 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 5ab4fe7e5d0e..78d086f3ab24 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> diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml index 908eaf5cf4a8..819250c47cc0 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 ab53dd3c1337..b5bbf2163352 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-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml index 2c42d8f76992..ca4122ee02fd 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 6447a3fef7a2..65a41bb5cf65 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 4157862b9655..13de03623ab2 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 b7862d9887f5..b70e2e56761d 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 871061031aec..746d6f45accd 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> @@ -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 c9b8495d25d1..9732fbd27470 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 09de767c2078..cc7f74055054 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> diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml index 165d8c033556..1f97ef6ea74d 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> @@ -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 ba63fc334149..78bc9918331c 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> diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml index 28bd4031f6bb..c181089321de 100644 --- a/packages/SystemUI/res/values-nb/strings.xml +++ b/packages/SystemUI/res/values-nb/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">"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 ea74b72ed9e9..a69be5d76035 100644 --- a/packages/SystemUI/res/values-ne/strings.xml +++ b/packages/SystemUI/res/values-ne/strings.xml @@ -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> @@ -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> diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml index 37c365742d08..e91f0a034842 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 722cdc9e768d..739885d4dbc8 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 456cb8ff1ae2..deca3ff30559 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 9eae3d4a9498..217b2f2fa971 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> @@ -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 1945c5d3ee77..6077c54a8e78 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 b75085f11e96..2e7c629b3849 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 1945c5d3ee77..6077c54a8e78 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 0abe4a009439..d6c3756b52c7 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> diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml index 6d41d9eb4d2c..33f47de80868 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 a719c920eb6f..cc27dfb7b1b2 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 ad33b0d3b730..0b74313dcf89 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> diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml index 4aea246b1254..b4729f4ec9f2 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 d7a5efa0f4bf..3ec14ea3fd81 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> @@ -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 9409e706b5c4..70fcb263ea6b 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 598dccbb6cec..623337079e3f 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 ac8c44f27b6d..f7e50effb982 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> diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml index c93bdd6f43b1..df52b0ed9fc1 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 ea22e5ba94b7..84b33a9bbf62 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> diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml index b7a0cc95cbc1..2b7bc5812b2a 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 f15e377491c5..8db4e9e76f2a 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 ae3d16b8f919..568be8a5a7d7 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> @@ -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 f1bd9b4347a4..7aef2526ab16 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 cf66b91ccd16..b8911fda4f7f 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> @@ -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 2cd285917b9d..f41193887e61 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> diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml index 8d90382d702d..1e10496573f1 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 19eeb8a97ae9..9272b8adb2c4 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> diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml index 481b92c130ca..fff99e4b876f 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> diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml index 58d9231ba96a..9a278fd1a0dc 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 e4ac66a98b2f..a11c5a82a9a0 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/attrs.xml b/packages/SystemUI/res/values/attrs.xml index 067d56f3d157..d2ed6017b205 100644 --- a/packages/SystemUI/res/values/attrs.xml +++ b/packages/SystemUI/res/values/attrs.xml @@ -143,6 +143,7 @@ <attr name="handleThickness" format="dimension" /> <attr name="handleColor" format="color" /> <attr name="scrimColor" format="color" /> + <attr name="containerBackgroundColor" format="color" /> <attr name="isVertical" format="boolean" /> @@ -178,6 +179,7 @@ <attr name="handleThickness" /> <attr name="handleColor" /> <attr name="scrimColor" /> + <attr name="containerBackgroundColor" /> </declare-styleable> <declare-styleable name="MagnifierView"> diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index b4deaa0af543..82ce881b2fbc 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -396,10 +396,6 @@ <!-- Whether or not the notifications should always fade as they are dismissed. --> <bool name="config_fadeNotificationsOnDismiss">false</bool> - <!-- Whether or not the parent of the notification row itself is being translated when swiped or - its children views. If true, then the contents are translated and vice versa. --> - <bool name="config_translateNotificationContentsOnSwipe">true</bool> - <!-- Whether or not the fade on the notification is based on the amount that it has been swiped off-screen. --> <bool name="config_fadeDependingOnAmountSwiped">false</bool> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 0022039a78ca..9b860c75f476 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -347,7 +347,7 @@ <!-- Padding to make tappable chip height 48dp (18+11+11+4+4) --> <dimen name="screenshot_action_chip_margin_vertical">4dp</dimen> <dimen name="screenshot_action_chip_padding_vertical">11dp</dimen> - <dimen name="screenshot_action_chip_icon_size">18dp</dimen> + <dimen name="screenshot_action_chip_icon_size">18sp</dimen> <!-- Padding on each side of the icon for icon-only chips --> <dimen name="screenshot_action_chip_icon_only_padding_horizontal">14dp</dimen> <!-- Padding at the edges of the chip for icon-and-text chips --> @@ -486,6 +486,9 @@ <dimen name="volume_dialog_slider_height">116dp</dimen> + <!-- (volume_dialog_panel_width - rounded_slider_icon_size) / 2 --> + <dimen name="volume_slider_icon_inset">11dp</dimen> + <dimen name="volume_dialog_track_width">4dp</dimen> <dimen name="volume_dialog_track_corner_radius">2dp</dimen> @@ -1236,7 +1239,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> @@ -1282,7 +1285,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> @@ -1292,7 +1295,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> @@ -1456,7 +1459,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/strings.xml b/packages/SystemUI/res/values/strings.xml index ccfe3e492a57..93ce8f3c2a96 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -2705,6 +2705,8 @@ <!-- Accessibility floating menu strings --> <!-- Message for the accessibility floating button migration tooltip. It shows when the user use gestural navigation then upgrade their system. It will tell the user the accessibility gesture had been replaced by accessibility floating button. [CHAR LIMIT=100] --> <string name="accessibility_floating_button_migration_tooltip">Accessibility button replaced the accessibility gesture\n\n<annotation id="link">View settings</annotation></string> + <!-- Message for the accessibility floating button settings tooltip. It shows when the user use gestural navigation then upgrade their system. It will tell the user to have another option to switch from the accessibility gesture to a button. [CHAR LIMIT=100] --> + <string name="accessibility_floating_button_switch_migration_tooltip">You can switch from the accessibility gesture to a button\n\n<annotation id="link">Settings</annotation></string> <!-- Message for the accessibility floating button docking tooltip. It shows when the user first time drag the button. It will tell the user about docking behavior. [CHAR LIMIT=70] --> <string name="accessibility_floating_button_docking_tooltip">Move button to the edge to hide it temporarily</string> <!-- Action in accessibility menu to move the accessibility floating button to the top left of the screen. [CHAR LIMIT=30] --> diff --git a/packages/SystemUI/res/xml/media_recommendation_collapsed.xml b/packages/SystemUI/res/xml/media_recommendation_collapsed.xml index 795c9087cec0..5c41ad82bd0b 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 3d03a9a3c52e..d8e132cc1208 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 fb9aa4a4b358..998b318915af 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 @@ -85,9 +85,7 @@ public class PipSurfaceTransactionHelper { final float left = destinationBounds.left - insets.left * scale; final float top = destinationBounds.top - insets.top * scale; mTmpTransform.setScale(scale, scale); - final Rect cornerRadiusRect = new Rect(destinationBounds); - cornerRadiusRect.inset(insets); - final float cornerRadius = getScaledCornerRadius(sourceBounds, cornerRadiusRect); + final float cornerRadius = getScaledCornerRadius(mTmpDestinationRect, destinationBounds); tx.setMatrix(leash, mTmpTransform, mTmpFloat9) .setWindowCrop(leash, mTmpDestinationRect) .setPosition(leash, left, top) @@ -110,15 +108,23 @@ public class PipSurfaceTransactionHelper { : (float) destinationBounds.height() / sourceBounds.height(); mTmpTransform.setRotate(degree, 0, 0); mTmpTransform.postScale(scale, scale); - final Rect cornerRadiusRect = new Rect(destinationBounds); - cornerRadiusRect.inset(insets); - final float cornerRadius = getScaledCornerRadius(sourceBounds, cornerRadiusRect); + 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) + .setPosition(leash, adjustedPositionX, adjustedPositionY) .setCornerRadius(leash, cornerRadius); return new PictureInPictureSurfaceTransaction( - positionX, positionY, mTmpFloat9, degree, cornerRadius, mTmpDestinationRect); + adjustedPositionX, adjustedPositionY, + mTmpFloat9, degree, cornerRadius, mTmpDestinationRect); } /** @return the round corner radius scaled by given from and to bounds */ diff --git a/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java b/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java index 92af58eb9af4..08076c17dc3a 100644 --- a/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java +++ b/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java @@ -127,8 +127,10 @@ public class AnimatableClockController extends ViewController<AnimatableClockVie @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 92ffb42d7921..ef052c4b81ac 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java @@ -288,20 +288,6 @@ public class KeyguardClockSwitch extends RelativeLayout { } /** - * 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 a7239cabcae5..ef6212d4f354 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java @@ -257,16 +257,6 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS } /** - * 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/KeyguardStatusViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java index 32935c293715..123c0e63d7d1 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java @@ -76,7 +76,7 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV mDozeParameters = dozeParameters; mKeyguardStateController = keyguardStateController; mKeyguardVisibilityHelper = new KeyguardVisibilityHelper(mView, keyguardStateController, - dozeParameters, unlockedScreenOffAnimationController); + dozeParameters, unlockedScreenOffAnimationController, /* animateYPos= */ true); mKeyguardUnlockAnimationController = keyguardUnlockAnimationController; mSmartspaceTransitionController = smartspaceTransitionController; @@ -187,16 +187,6 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV } /** - * 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() { diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index 3d51f2379727..f3a6d6377c6d 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -66,10 +66,8 @@ import android.os.Handler; import android.os.IRemoteCallback; import android.os.Looper; import android.os.Message; -import android.os.PowerManager; import android.os.RemoteException; import android.os.ServiceManager; -import android.os.SystemClock; import android.os.Trace; import android.os.UserHandle; import android.os.UserManager; @@ -243,21 +241,14 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab private final boolean mIsPrimaryUser; private final boolean mIsAutomotive; private final AuthController mAuthController; - private final PowerManager mPowerManager; private final StatusBarStateController mStatusBarStateController; private int mStatusBarState; - private boolean mDozing; private final StatusBarStateController.StateListener mStatusBarStateControllerListener = new StatusBarStateController.StateListener() { @Override public void onStateChanged(int newState) { mStatusBarState = newState; } - - @Override - public void onDozingChanged(boolean dozing) { - mDozing = dozing; - } }; HashMap<Integer, SimData> mSimDatas = new HashMap<>(); @@ -1330,19 +1321,16 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab private final FingerprintManager.AuthenticationCallback mFingerprintAuthenticationCallback = new AuthenticationCallback() { - private boolean mIsUdfpsRunningWhileDozing; @Override public void onAuthenticationFailed() { handleFingerprintAuthFailed(); - cancelAodInterrupt(); } @Override public void onAuthenticationSucceeded(AuthenticationResult result) { Trace.beginSection("KeyguardUpdateMonitor#onAuthenticationSucceeded"); handleFingerprintAuthenticated(result.getUserId(), result.isStrongBiometric()); - cancelAodInterrupt(); Trace.endSection(); } @@ -1354,7 +1342,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab @Override public void onAuthenticationError(int errMsgId, CharSequence errString) { handleFingerprintError(errMsgId, errString.toString()); - cancelAodInterrupt(); } @Override @@ -1365,25 +1352,12 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab @Override public void onUdfpsPointerDown(int sensorId) { Log.d(TAG, "onUdfpsPointerDown, sensorId: " + sensorId); - - if (mDozing) { - mIsUdfpsRunningWhileDozing = true; - } } @Override public void onUdfpsPointerUp(int sensorId) { Log.d(TAG, "onUdfpsPointerUp, sensorId: " + sensorId); } - - private void cancelAodInterrupt() { - if (mIsUdfpsRunningWhileDozing) { - mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE, - "com.android.systemui:AOD_INTERRUPT_END"); - } - mAuthController.onCancelUdfps(); - mIsUdfpsRunningWhileDozing = false; - } }; private final FaceManager.FaceDetectionCallback mFaceDetectionCallback @@ -1676,7 +1650,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab LockPatternUtils lockPatternUtils, AuthController authController, TelephonyListenerManager telephonyListenerManager, - PowerManager powerManager, FeatureFlags featureFlags) { mContext = context; mSubscriptionManager = SubscriptionManager.from(context); @@ -1689,10 +1662,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab mStatusBarStateController = statusBarStateController; mStatusBarStateController.addCallback(mStatusBarStateControllerListener); mStatusBarState = mStatusBarStateController.getState(); - mDozing = mStatusBarStateController.isDozing(); mLockPatternUtils = lockPatternUtils; mAuthController = authController; - mPowerManager = powerManager; dumpManager.registerDumpable(getClass().getName(), this); mHandler = new Handler(mainLooper) { diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java b/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java index 7edecc80a27e..28a54d56b071 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java @@ -19,6 +19,7 @@ package com.android.keyguard; 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 @@ public class KeyguardVisibilityHelper { 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 class KeyguardVisibilityHelper { 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 @@ public class KeyguardVisibilityHelper { } 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 cdb39ef216bc..5e874ae6f44e 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.AnimatorListenerAdapter 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 @@ class TextAnimator( }) } + private val typefaceCache = SparseArray<Typeface?>() + fun updateLayout(layout: Layout) { textInterpolator.layout = layout } @@ -120,7 +124,12 @@ class TextAnimator( 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 @@ class TextAnimator( } } } + +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/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java index b0f4da251208..affad7a57d86 100644 --- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java +++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java @@ -391,9 +391,9 @@ public class SwipeHelper implements Gefingerpoken { boolean animateLeft = (Math.abs(velocity) > getEscapeVelocity() && velocity < 0) || (getTranslation(animView) < 0 && !isDismissAll); if (animateLeft || animateLeftForRtl || animateUpForMenu) { - newPos = -getSize(animView); + newPos = -getTotalTranslationLength(animView); } else { - newPos = getSize(animView); + newPos = getTotalTranslationLength(animView); } long duration; if (fixedDuration == 0) { @@ -470,6 +470,15 @@ public class SwipeHelper implements Gefingerpoken { } /** + * Get the total translation length where we want to swipe to when dismissing the view. By + * default this is the size of the view, but can also be larger. + * @param animView the view to ask about + */ + protected float getTotalTranslationLength(View animView) { + return getSize(animView); + } + + /** * Called to update the dismiss animation. */ protected void prepareDismissAnimation(View view, Animator anim) { diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java index bfb7105f5860..17178fa8e606 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java @@ -75,7 +75,6 @@ class MagnificationModeSwitch implements MagnificationGestureDetector.OnGestureL private final SfVsyncFrameCallbackProvider mSfVsyncFrameProvider; private int mMagnificationMode = ACCESSIBILITY_MAGNIFICATION_MODE_NONE; private final LayoutParams mParams; - private int mWindowHeight; @VisibleForTesting final Rect mDraggableWindowBounds = new Rect(); private boolean mIsVisible = false; @@ -95,7 +94,6 @@ class MagnificationModeSwitch implements MagnificationGestureDetector.OnGestureL mWindowManager = mContext.getSystemService(WindowManager.class); mSfVsyncFrameProvider = sfVsyncFrameProvider; mParams = createLayoutParams(context); - mWindowHeight = mWindowManager.getCurrentWindowMetrics().getBounds().height(); mImageView = imageView; mImageView.setOnTouchListener(this::onTouch); mImageView.setAccessibilityDelegate(new View.AccessibilityDelegate() { @@ -313,12 +311,14 @@ class MagnificationModeSwitch implements MagnificationGestureDetector.OnGestureL void onConfigurationChanged(int configDiff) { if ((configDiff & ActivityInfo.CONFIG_ORIENTATION) != 0) { + final Rect previousDraggableBounds = new Rect(mDraggableWindowBounds); mDraggableWindowBounds.set(getDraggableWindowBounds()); - // Keep the Y position with the same height ratio before the window height is changed. - final int windowHeight = mWindowManager.getCurrentWindowMetrics().getBounds().height(); - final float windowHeightFraction = (float) mParams.y / mWindowHeight; - mParams.y = (int) (windowHeight * windowHeightFraction); - mWindowHeight = windowHeight; + // Keep the Y position with the same height ratio before the window bounds and + // draggable bounds are changed. + final float windowHeightFraction = (float) (mParams.y - previousDraggableBounds.top) + / previousDraggableBounds.height(); + mParams.y = (int) (windowHeightFraction * mDraggableWindowBounds.height()) + + mDraggableWindowBounds.top; stickToScreenEdge(mToLeftScreenEdge); return; } diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenu.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenu.java index 47f373920b90..05256e646948 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenu.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenu.java @@ -53,7 +53,7 @@ public class AccessibilityFloatingMenu implements IAccessibilityFloatingMenu { @FloatRange(from = 0.0, to = 1.0) private static final float DEFAULT_POSITION_X_PERCENT = 1.0f; @FloatRange(from = 0.0, to = 1.0) - private static final float DEFAULT_POSITION_Y_PERCENT = 0.8f; + private static final float DEFAULT_POSITION_Y_PERCENT = 0.9f; private final Context mContext; private final AccessibilityFloatingMenuView mMenuView; diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityTargetAdapter.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityTargetAdapter.java index 63cfd5123c96..ee09c620ec1d 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityTargetAdapter.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityTargetAdapter.java @@ -143,7 +143,7 @@ public class AccessibilityTargetAdapter extends Adapter<ViewHolder> { } void updateItemPadding(int padding, int size) { - itemView.setPaddingRelative(padding, padding, padding, padding); + itemView.setPaddingRelative(padding, padding, padding, 0); } } @@ -154,7 +154,7 @@ public class AccessibilityTargetAdapter extends Adapter<ViewHolder> { @Override void updateItemPadding(int padding, int size) { - final int paddingBottom = size <= 2 ? padding : 0; + final int paddingBottom = size <= 1 ? padding : 0; itemView.setPaddingRelative(padding, padding, padding, paddingBottom); } } @@ -166,7 +166,7 @@ public class AccessibilityTargetAdapter extends Adapter<ViewHolder> { @Override void updateItemPadding(int padding, int size) { - itemView.setPaddingRelative(padding, 0, padding, padding); + itemView.setPaddingRelative(padding, padding, padding, padding); } } } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java index d1cb6ec7a072..c4f78e7782a2 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 @@ public class AuthContainerView extends LinearLayout 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 @@ public class AuthContainerView extends LinearLayout } 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/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java index 5e6b904c1527..7947241ff794 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java @@ -43,6 +43,7 @@ import android.hardware.face.FaceSensorPropertiesInternal; import android.hardware.fingerprint.FingerprintManager; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback; +import android.hardware.fingerprint.IUdfpsHbmListener; import android.os.Bundle; import android.os.Handler; import android.os.Looper; @@ -100,6 +101,8 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks, @Nullable private UdfpsController mUdfpsController; @Nullable + private IUdfpsHbmListener mUdfpsHbmListener; + @Nullable private SidefpsController mSidefpsController; @VisibleForTesting TaskStackListener mTaskStackListener; @@ -470,6 +473,24 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks, mActivityTaskManager.registerTaskStackListener(mTaskStackListener); } + /** + * Stores the listener received from {@link com.android.server.display.DisplayModeDirector}. + * + * DisplayModeDirector implements {@link IUdfpsHbmListener} and registers it with this class by + * calling {@link CommandQueue#setUdfpsHbmListener(IUdfpsHbmListener)}. + */ + @Override + public void setUdfpsHbmListener(IUdfpsHbmListener listener) { + mUdfpsHbmListener = listener; + } + + /** + * @return IUdfpsHbmListener that can be set by DisplayModeDirector. + */ + @Nullable public IUdfpsHbmListener getUdfpsHbmListener() { + return mUdfpsHbmListener; + } + @Override public void showAuthenticationDialog(PromptInfo promptInfo, IBiometricSysuiReceiver receiver, int[] sensorIds, boolean credentialAllowed, boolean requireConfirmation, diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java index dd339abb3a40..ec930b0c41d1 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java @@ -378,6 +378,7 @@ public class UdfpsController implements DozeReceiver { return true; case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_HOVER_ENTER: + Trace.beginSection("UdfpsController.onTouch.ACTION_DOWN"); // To simplify the lifecycle of the velocity tracker, make sure it's never null // after ACTION_DOWN, and always null after ACTION_CANCEL or ACTION_UP. if (mVelocityTracker == null) { @@ -388,8 +389,7 @@ public class UdfpsController implements DozeReceiver { mVelocityTracker.clear(); } if (isWithinSensorArea(udfpsView, event.getX(), event.getY(), fromUdfpsView)) { - Trace.beginAsyncSection( - "UdfpsController#ACTION_DOWN", 1); + Trace.beginAsyncSection("UdfpsController.e2e.onPointerDown", 0); // The pointer that causes ACTION_DOWN is always at index 0. // We need to persist its ID to track it during ACTION_MOVE that could include // data for many other pointers because of multi-touch support. @@ -397,17 +397,18 @@ public class UdfpsController implements DozeReceiver { mVelocityTracker.addMovement(event); handled = true; } + Trace.endSection(); break; case MotionEvent.ACTION_MOVE: case MotionEvent.ACTION_HOVER_MOVE: + Trace.beginSection("UdfpsController.onTouch.ACTION_MOVE"); final int idx = mActivePointerId == -1 ? 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). @@ -427,7 +428,8 @@ public class UdfpsController implements DozeReceiver { 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(), @@ -466,11 +468,13 @@ public class UdfpsController implements DozeReceiver { onFingerUp(); } } + Trace.endSection(); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_HOVER_EXIT: + Trace.beginSection("UdfpsController.onTouch.ACTION_UP"); mActivePointerId = -1; if (mVelocityTracker != null) { mVelocityTracker.recycle(); @@ -479,7 +483,7 @@ public class UdfpsController implements DozeReceiver { Log.v(TAG, "onTouch | finger up"); onFingerUp(); mFalsingManager.isFalseTouch(UDFPS_AUTHENTICATION); - + Trace.endSection(); break; default: @@ -818,12 +822,11 @@ public class UdfpsController implements DozeReceiver { return; } mFingerprintManager.onPointerDown(mSensorProps.sensorId, x, y, minor, major); - Trace.endAsyncSection( - "UdfpsController#ACTION_DOWN", 1); - Trace.beginAsyncSection("UdfpsController#startIllumination", 1); + Trace.endAsyncSection("UdfpsController.e2e.onPointerDown", 0); + Trace.beginAsyncSection("UdfpsController.e2e.startIllumination", 0); mView.startIllumination(() -> { mFingerprintManager.onUiReady(mSensorProps.sensorId); - Trace.endAsyncSection("UdfpsController#startIllumination", 1); + Trace.endAsyncSection("UdfpsController.e2e.startIllumination", 0); }); } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java index 750d42c0a848..00888dfe48d3 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java @@ -355,10 +355,13 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud @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 af7089296bca..567d0cb3e6cb 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt @@ -422,8 +422,12 @@ class ControlsUiControllerImpl @Inject constructor ( // 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/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java index 39adabb06d40..23c44131ab60 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java @@ -70,6 +70,7 @@ public class DozeSensors { private final Consumer<Boolean> mProxCallback; private final SecureSettings mSecureSettings; private final Callback mCallback; + private final boolean mScreenOffUdfpsEnabled; @VisibleForTesting protected TriggerSensor[] mSensors; @@ -116,6 +117,8 @@ public class DozeSensors { mProximitySensor = proximitySensor; mSelectivelyRegisterProxSensors = dozeParameters.getSelectivelyRegisterSensorsUsingProx(); mListeningProxSensors = !mSelectivelyRegisterProxSensors; + mScreenOffUdfpsEnabled = + config.screenOffUdfpsEnabled(KeyguardUpdateMonitor.getCurrentUser()); boolean udfpsEnrolled = authController.isUdfpsEnrolled(KeyguardUpdateMonitor.getCurrentUser()); @@ -171,7 +174,7 @@ public class DozeSensors { findSensorWithType(config.udfpsLongPressSensorType()), "doze_pulse_on_auth", true /* settingDef */, - udfpsEnrolled, + udfpsEnrolled && (alwaysOn || mScreenOffUdfpsEnabled), DozeLog.REASON_SENSOR_UDFPS_LONG_PRESS, true /* reports touch coordinates */, true /* touchscreen */, @@ -369,6 +372,7 @@ public class DozeSensors { pw.println("mListeningTouchScreenSensors=" + mListeningTouchScreenSensors); pw.println("mSelectivelyRegisterProxSensors=" + mSelectivelyRegisterProxSensors); pw.println("mListeningProxSensors=" + mListeningProxSensors); + pw.println("mScreenOffUdfpsEnabled=" + mScreenOffUdfpsEnabled); IndentingPrintWriter idpw = new IndentingPrintWriter(pw); idpw.increaseIndent(); for (TriggerSensor s : mSensors) { diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java index c45eb3558948..ff95604088ed 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 @@ public class DozeTriggers implements DozeMachine.Part { // 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/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java index dfd85fe4dc90..1fb36d7fbd3b 100644 --- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java +++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java @@ -72,6 +72,7 @@ import com.android.systemui.plugins.GlobalActions.GlobalActionsManager; import com.android.systemui.plugins.GlobalActionsPanelPlugin; import com.android.systemui.statusbar.NotificationShadeDepthController; import com.android.systemui.statusbar.NotificationShadeWindowController; +import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.telephony.TelephonyListenerManager; @@ -133,7 +134,8 @@ public class GlobalActionsDialog extends GlobalActionsDialogLite IWindowManager iWindowManager, @Background Executor backgroundExecutor, UiEventLogger uiEventLogger, - RingerModeTracker ringerModeTracker, SysUiState sysUiState, @Main Handler handler) { + RingerModeTracker ringerModeTracker, SysUiState sysUiState, @Main Handler handler, + StatusBar statusBar) { super(context, windowManagerFuncs, audioManager, iDreamManager, @@ -152,7 +154,7 @@ public class GlobalActionsDialog extends GlobalActionsDialogLite backgroundExecutor, uiEventLogger, null, - ringerModeTracker, sysUiState, handler); + ringerModeTracker, sysUiState, handler, statusBar); mLockPatternUtils = lockPatternUtils; mKeyguardStateController = keyguardStateController; @@ -227,7 +229,8 @@ public class GlobalActionsDialog extends GlobalActionsDialogLite ActionsDialog dialog = new ActionsDialog(getContext(), mAdapter, mOverflowAdapter, this::getWalletViewController, mDepthController, mSysuiColorExtractor, mStatusBarService, mNotificationShadeWindowController, - mSysUiState, this::onRotate, isKeyguardShowing(), mPowerAdapter, getEventLogger()); + mSysUiState, this::onRotate, isKeyguardShowing(), mPowerAdapter, getEventLogger(), + getStatusBar()); if (shouldShowLockMessage(dialog)) { dialog.showLockMessage(); @@ -295,11 +298,13 @@ public class GlobalActionsDialog extends GlobalActionsDialogLite SysuiColorExtractor sysuiColorExtractor, IStatusBarService statusBarService, NotificationShadeWindowController notificationShadeWindowController, SysUiState sysuiState, Runnable onRotateCallback, boolean keyguardShowing, - MyPowerOptionsAdapter powerAdapter, UiEventLogger uiEventLogger) { + MyPowerOptionsAdapter powerAdapter, UiEventLogger uiEventLogger, + StatusBar statusBar) { super(context, com.android.systemui.R.style.Theme_SystemUI_Dialog_GlobalActions, adapter, overflowAdapter, depthController, sysuiColorExtractor, statusBarService, notificationShadeWindowController, sysuiState, - onRotateCallback, keyguardShowing, powerAdapter, uiEventLogger, null); + onRotateCallback, keyguardShowing, powerAdapter, uiEventLogger, null, + statusBar); mWalletFactory = walletFactory; // Update window attributes diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java index 8e152830e208..ad920cbc0192 100644 --- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java +++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java @@ -74,8 +74,10 @@ import android.telephony.TelephonyManager; import android.util.ArraySet; import android.util.Log; import android.view.ContextThemeWrapper; +import android.view.GestureDetector; import android.view.IWindowManager; import android.view.LayoutInflater; +import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.Window; @@ -119,6 +121,7 @@ import com.android.systemui.plugins.GlobalActionsPanelPlugin; import com.android.systemui.scrim.ScrimDrawable; import com.android.systemui.statusbar.NotificationShadeDepthController; import com.android.systemui.statusbar.NotificationShadeWindowController; +import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.telephony.TelephonyListenerManager; @@ -228,6 +231,7 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene private int mDialogPressDelay = DIALOG_PRESS_DELAY; // ms protected Handler mMainHandler; private int mSmallestScreenWidthDp; + private final StatusBar mStatusBar; @VisibleForTesting public enum GlobalActionsEvent implements UiEventLogger.UiEventEnum { @@ -322,7 +326,8 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene @Background Executor backgroundExecutor, UiEventLogger uiEventLogger, GlobalActionsInfoProvider infoProvider, - RingerModeTracker ringerModeTracker, SysUiState sysUiState, @Main Handler handler) { + RingerModeTracker ringerModeTracker, SysUiState sysUiState, @Main Handler handler, + StatusBar statusBar) { mContext = context; mWindowManagerFuncs = windowManagerFuncs; mAudioManager = audioManager; @@ -352,6 +357,7 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene mSysUiState = sysUiState; mMainHandler = handler; mSmallestScreenWidthDp = mContext.getResources().getConfiguration().smallestScreenWidthDp; + mStatusBar = statusBar; // receive broadcasts IntentFilter filter = new IntentFilter(); @@ -392,6 +398,10 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene return mUiEventLogger; } + protected StatusBar getStatusBar() { + return mStatusBar; + } + /** * Show the global actions dialog (creating if necessary) * @@ -625,7 +635,7 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene mDepthController, mSysuiColorExtractor, mStatusBarService, mNotificationShadeWindowController, mSysUiState, this::onRotate, mKeyguardShowing, mPowerAdapter, mUiEventLogger, - mInfoProvider); + mInfoProvider, mStatusBar); dialog.setOnDismissListener(this); dialog.setOnShowListener(this); @@ -2100,9 +2110,53 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene protected final Runnable mOnRotateCallback; private UiEventLogger mUiEventLogger; private GlobalActionsInfoProvider mInfoProvider; + private GestureDetector mGestureDetector; + private StatusBar mStatusBar; protected ViewGroup mContainer; + @VisibleForTesting + protected GestureDetector.SimpleOnGestureListener mGestureListener = + new GestureDetector.SimpleOnGestureListener() { + @Override + public boolean onDown(MotionEvent e) { + // All gestures begin with this message, so continue listening + return true; + } + + @Override + public boolean onSingleTapConfirmed(MotionEvent e) { + // Close without opening shade + mUiEventLogger.log(GlobalActionsEvent.GA_CLOSE_TAP_OUTSIDE); + cancel(); + return false; + } + + @Override + public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, + float distanceY) { + if (distanceY < 0 && distanceY > distanceX + && e1.getY() <= mStatusBar.getStatusBarHeight()) { + // Downwards scroll from top + openShadeAndDismiss(); + return true; + } + return false; + } + + @Override + public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, + float velocityY) { + if (velocityY > 0 && Math.abs(velocityY) > Math.abs(velocityX) + && e1.getY() <= mStatusBar.getStatusBarHeight()) { + // Downwards fling from top + openShadeAndDismiss(); + return true; + } + return false; + } + }; + ActionsDialogLite(Context context, int themeRes, MyAdapter adapter, MyOverflowAdapter overflowAdapter, NotificationShadeDepthController depthController, @@ -2110,7 +2164,7 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene NotificationShadeWindowController notificationShadeWindowController, SysUiState sysuiState, Runnable onRotateCallback, boolean keyguardShowing, MyPowerOptionsAdapter powerAdapter, UiEventLogger uiEventLogger, - @Nullable GlobalActionsInfoProvider infoProvider) { + @Nullable GlobalActionsInfoProvider infoProvider, StatusBar statusBar) { super(context, themeRes); mContext = context; mAdapter = adapter; @@ -2125,6 +2179,9 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene mKeyguardShowing = keyguardShowing; mUiEventLogger = uiEventLogger; mInfoProvider = infoProvider; + mStatusBar = statusBar; + + mGestureDetector = new GestureDetector(mContext, mGestureListener); // Window initialization Window window = getWindow(); @@ -2146,6 +2203,23 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene initializeLayout(); } + @Override + public boolean onTouchEvent(MotionEvent event) { + return mGestureDetector.onTouchEvent(event) || super.onTouchEvent(event); + } + + private void openShadeAndDismiss() { + mUiEventLogger.log(GlobalActionsEvent.GA_CLOSE_TAP_OUTSIDE); + if (mStatusBar.isKeyguardShowing()) { + // match existing lockscreen behavior to open QS when swiping from status bar + mStatusBar.animateExpandSettingsPanel(null); + } else { + // otherwise, swiping down should expand notification shade + mStatusBar.animateExpandNotificationsPanel(); + } + dismiss(); + } + private ListPopupWindow createPowerOverflowPopup() { GlobalActionsPopupMenu popup = new GlobalActionsPopupMenu( new ContextThemeWrapper( @@ -2194,9 +2268,9 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene mGlobalActionsLayout.setRotationListener(this::onRotate); mGlobalActionsLayout.setAdapter(mAdapter); mContainer = findViewById(com.android.systemui.R.id.global_actions_container); - mContainer.setOnClickListener(v -> { - mUiEventLogger.log(GlobalActionsEvent.GA_CLOSE_TAP_OUTSIDE); - cancel(); + mContainer.setOnTouchListener((v, event) -> { + mGestureDetector.onTouchEvent(event); + return v.onTouchEvent(event); }); View overflowButton = findViewById( diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java index 5a5cce8f5093..70837385b858 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.IKeyguardExitCallback; 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 @@ public class KeyguardService extends Service { * 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 @@ public class KeyguardService extends Service { 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 665376ac4569..38d153e38ca9 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 @@ class KeyguardUnlockAnimationController @Inject constructor( // 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 @@ class KeyguardUnlockAnimationController @Inject constructor( } surfaceBehindEntryAnimator.addListener(object : AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator) { - keyguardViewMediator.get().onKeyguardExitRemoteAnimationFinished() + keyguardViewMediator.get().onKeyguardExitRemoteAnimationFinished( + false /* cancelled */) } }) @@ -317,7 +319,7 @@ class KeyguardUnlockAnimationController @Inject constructor( } override fun onKeyguardDismissAmountChanged() { - if (!KeyguardService.sEnableRemoteKeyguardAnimation) { + if (!KeyguardService.sEnableRemoteKeyguardGoingAwayAnimation) { return } @@ -370,7 +372,7 @@ class KeyguardUnlockAnimationController @Inject constructor( } 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 56efafba4640..327698392ac7 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -1655,7 +1655,8 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable, * 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. + * 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 (!mKeyguardDonePending) { @@ -2022,6 +2023,7 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable, } mHiding = false; + mKeyguardExitAnimationRunner = null; mWakeAndUnlocking = false; mPendingLock = false; setShowingLocked(true); @@ -2157,6 +2159,8 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable, return; } mHiding = false; + IRemoteAnimationRunner runner = mKeyguardExitAnimationRunner; + mKeyguardExitAnimationRunner = null; if (mWakeAndUnlocking && mDrawnCallback != null) { @@ -2177,17 +2181,18 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable, 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 */); @@ -2211,7 +2216,7 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable, // 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; @@ -2315,15 +2320,15 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable, } /** - * 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 */); } /** @@ -2332,8 +2337,10 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable, * 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; } @@ -2347,7 +2354,7 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable, mKeyguardUnlockAnimationControllerLazy.get().hideKeyguardViewAfterRemoteAnimation(); } - finishSurfaceBehindRemoteAnimation(); + finishSurfaceBehindRemoteAnimation(cancelled); mSurfaceBehindRemoteAnimationRequested = false; mKeyguardUnlockAnimationControllerLazy.get().notifyFinishedKeyguardExitAnimation(); InteractionJankMonitor.getInstance().end(CUJ_LOCKSCREEN_UNLOCK_ANIMATION); @@ -2389,12 +2396,14 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable, } /** 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(); @@ -2638,10 +2647,10 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable, } /** - * 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 18d2c9183bb6..1004e257c750 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 @@ class MediaCarouselController @Inject constructor( visualStabilityCallback = VisualStabilityManager.Callback { if (needsReordering) { needsReordering = false - reorderAllPlayers() + reorderAllPlayers(previousVisiblePlayerKey = null) } keysNeedRemoval.forEach { removePlayer(it) } @@ -285,7 +285,7 @@ class MediaCarouselController @Inject constructor( 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 @@ class MediaCarouselController @Inject constructor( // 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 @@ class MediaCarouselController @Inject constructor( 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 @@ class MediaCarouselController @Inject constructor( 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 @@ class MediaCarouselController @Inject constructor( 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 @@ internal object MediaPlayerData { ) 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 @@ internal object MediaPlayerData { 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 @@ internal object MediaPlayerData { 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 45ceceba5cba..eb3549789c19 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 @@ class MediaCarouselScrollHandler( 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 4201411b168a..19190cd4a17d 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.media.session.PlaybackState; 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,7 @@ import androidx.annotation.Nullable; import androidx.annotation.UiThread; import androidx.constraintlayout.widget.ConstraintSet; -import com.android.settingslib.Utils; +import com.android.internal.jank.InteractionJankMonitor; import com.android.settingslib.widget.AdaptiveIcon; import com.android.systemui.R; import com.android.systemui.animation.ActivityLaunchAnimator; @@ -468,7 +469,8 @@ public class MediaControlPanel { TransitionLayout player) { // TODO(b/174236650): Make sure that the carousel indicator also fades out. // TODO(b/174236650): Instrument the animation to measure jank. - return new GhostedViewLaunchAnimatorController(player) { + return new GhostedViewLaunchAnimatorController(player, + InteractionJankMonitor.CUJ_SHADE_APP_LAUNCH_FROM_MEDIA_PLAYER) { @Override protected float getCurrentTopCornerRadius() { return ((IlluminationDrawable) player.getBackground()).getCornerRadius(); @@ -542,7 +544,10 @@ public class MediaControlPanel { 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(), @@ -561,7 +566,8 @@ public class MediaControlPanel { 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() @@ -581,12 +587,18 @@ public class MediaControlPanel { 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 13c7f71f53ee..5b1e039ad0f8 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 @@ class MediaDataManager( * 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/MediaHierarchyManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt index 075bc700cfa0..edbf18789e28 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt @@ -187,6 +187,12 @@ class MediaHierarchyManager @Inject constructor( private var currentAttachmentLocation = -1 /** + * Is there any active media in the carousel? + */ + private var hasActiveMedia: Boolean = false + get() = mediaHosts.get(LOCATION_QQS)?.visible == true + + /** * Are we currently waiting on an animation to start? */ private var animationPending: Boolean = false @@ -476,8 +482,12 @@ class MediaHierarchyManager @Inject constructor( val viewHost = createUniqueObjectHost() mediaObject.hostView = viewHost mediaObject.addVisibilityChangeListener { + // If QQS changes visibility, we need to force an update to ensure the transition + // goes into the correct state + val stateUpdate = mediaObject.location == LOCATION_QQS + // Never animate because of a visibility change, only state changes should do that - updateDesiredLocation(forceNoAnimation = true) + updateDesiredLocation(forceNoAnimation = true, forceStateUpdate = stateUpdate) } mediaHosts[mediaObject.location] = mediaObject if (mediaObject.location == desiredLocation) { @@ -521,10 +531,15 @@ class MediaHierarchyManager @Inject constructor( * going from the old desired location to the new one. * * @param forceNoAnimation optional parameter telling the system not to animate + * @param forceStateUpdate optional parameter telling the system to update transition state + * even if location did not change */ - private fun updateDesiredLocation(forceNoAnimation: Boolean = false) { + private fun updateDesiredLocation( + forceNoAnimation: Boolean = false, + forceStateUpdate: Boolean = false + ) { val desiredLocation = calculateLocation() - if (desiredLocation != this.desiredLocation) { + if (desiredLocation != this.desiredLocation || forceStateUpdate) { if (this.desiredLocation >= 0) { previousLocation = this.desiredLocation } @@ -784,7 +799,7 @@ class MediaHierarchyManager @Inject constructor( private fun getQSTransformationProgress(): Float { val currentHost = getHost(desiredLocation) val previousHost = getHost(previousLocation) - if (currentHost?.location == LOCATION_QS) { + if (hasActiveMedia && currentHost?.location == LOCATION_QS) { if (previousHost?.location == LOCATION_QQS) { if (previousHost.visible || statusbarState != StatusBarState.KEYGUARD) { return qsExpansion @@ -917,6 +932,7 @@ class MediaHierarchyManager @Inject constructor( val location = when { qsExpansion > 0.0f && !onLockscreen -> LOCATION_QS qsExpansion > 0.4f && onLockscreen -> LOCATION_QS + !hasActiveMedia -> LOCATION_QS onLockscreen && isTransformingToFullShadeAndInQQS() -> LOCATION_QQS onLockscreen && allowedOnLockscreen -> LOCATION_LOCKSCREEN else -> LOCATION_QQS diff --git a/packages/SystemUI/src/com/android/systemui/media/RecommendationViewHolder.kt b/packages/SystemUI/src/com/android/systemui/media/RecommendationViewHolder.kt index 78619d652c6c..142628cff448 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 @@ class RecommendationViewHolder private constructor(itemView: View) { 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 @@ class RecommendationViewHolder private constructor(itemView: View) { 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 @@ class RecommendationViewHolder private constructor(itemView: View) { 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 @@ class RecommendationViewHolder private constructor(itemView: View) { 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 3e5e14095929..da09793580bb 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 @@ public class NavigationBar implements View.OnAttachStateChangeListener, 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); 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 8838d7e5e87a..0d9749e05262 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 @@ public class EdgeBackGestureHandler extends CurrentUserTracker 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 @@ public class EdgeBackGestureHandler extends CurrentUserTracker 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 @@ public class EdgeBackGestureHandler extends CurrentUserTracker private boolean mIsNavBarShownTransiently; private boolean mIsBackGestureAllowed; private boolean mGestureBlockingActivityRunning; + private boolean mIsInPipMode; private InputMonitor mInputMonitor; private InputChannelCompat.InputEventReceiver mInputEventReceiver; @@ -533,16 +544,16 @@ public class EdgeBackGestureHandler extends CurrentUserTracker 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 @@ public class EdgeBackGestureHandler extends CurrentUserTracker // 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 @@ public class EdgeBackGestureHandler extends CurrentUserTracker 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/PeopleSpaceActivity.java b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java index 6a025a750baa..d9e2648750a4 100644 --- a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java +++ b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java @@ -91,8 +91,8 @@ public class PeopleSpaceActivity extends Activity { // than the activity's background. LinearLayout item = findViewById(R.id.item); GradientDrawable shape = (GradientDrawable) item.getBackground(); - final TypedArray ta = mContext.obtainStyledAttributes( - new int[]{android.R.attr.colorBackgroundFloating}); + final TypedArray ta = mContext.getTheme().obtainStyledAttributes( + new int[]{com.android.internal.R.attr.colorSurface}); shape.setColor(ta.getColor(0, Color.WHITE)); return; } diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java b/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java index 72d382ac0799..32fdf0ea4de6 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 @@ public class PeopleTileViewHelper { } 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 @@ public class PeopleTileViewHelper { 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 @@ public class PeopleTileViewHelper { } 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 @@ public class PeopleTileViewHelper { // 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 @@ public class PeopleTileViewHelper { 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/LaunchConversationActivity.java b/packages/SystemUI/src/com/android/systemui/people/widget/LaunchConversationActivity.java index c416b5edb264..b031637e4016 100644 --- a/packages/SystemUI/src/com/android/systemui/people/widget/LaunchConversationActivity.java +++ b/packages/SystemUI/src/com/android/systemui/people/widget/LaunchConversationActivity.java @@ -35,9 +35,11 @@ import com.android.internal.logging.UiEventLoggerImpl; import com.android.internal.statusbar.IStatusBarService; import com.android.internal.statusbar.NotificationVisibility; import com.android.systemui.people.PeopleSpaceUtils; +import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.wmshell.BubblesManager; +import com.android.wm.shell.bubbles.Bubble; import java.util.Optional; @@ -53,14 +55,35 @@ public class LaunchConversationActivity extends Activity { private final UserManager mUserManager; private boolean mIsForTesting; private IStatusBarService mIStatusBarService; + private CommandQueue mCommandQueue; + private Bubble mBubble; + private NotificationEntry mEntryToBubble; @Inject public LaunchConversationActivity(NotificationEntryManager notificationEntryManager, - Optional<BubblesManager> bubblesManagerOptional, UserManager userManager) { + Optional<BubblesManager> bubblesManagerOptional, UserManager userManager, + CommandQueue commandQueue) { super(); mNotificationEntryManager = notificationEntryManager; mBubblesManagerOptional = bubblesManagerOptional; mUserManager = userManager; + mCommandQueue = commandQueue; + mCommandQueue.addCallback(new CommandQueue.Callbacks() { + // (b/190833924) Wait for the app transition to finish before showing the bubble, + // opening the bubble while the transition is happening can mess with the placement + // of the bubble's surface. + @Override + public void appTransitionFinished(int displayId) { + if (mBubblesManagerOptional.isPresent()) { + if (mBubble != null) { + mBubblesManagerOptional.get().expandStackAndSelectBubble(mBubble); + } else if (mEntryToBubble != null) { + mBubblesManagerOptional.get().expandStackAndSelectBubble(mEntryToBubble); + } + } + mCommandQueue.removeCallback(this); + } + }); } @Override @@ -95,14 +118,28 @@ public class LaunchConversationActivity extends Activity { return; } - NotificationEntry entry = mNotificationEntryManager.getPendingOrActiveNotif( - notificationKey); - if (entry != null && entry.canBubble() && mBubblesManagerOptional.isPresent()) { - if (DEBUG) Log.d(TAG, "Open bubble for conversation"); - mBubblesManagerOptional.get().expandStackAndSelectBubble(entry); - // Just opt-out and don't cancel the notification for bubbles. - finish(); - return; + // We can potentially bubble without a notification, so rather than rely on + // notificationKey here (which could be null if there's no notification or if the + // bubble is suppressing the notification), so we'll use the shortcutId for lookups. + // This misses one specific case: a bubble that was never opened & still has a + // visible notification, but the bubble was dismissed & aged out of the overflow. + // So it wouldn't exist in the stack or overflow to be looked up BUT the notif entry + // would still exist & be bubbleable. So if we don't get a bubble from the + // shortcutId, fallback to notificationKey if it exists. + if (mBubblesManagerOptional.isPresent()) { + mBubble = mBubblesManagerOptional.get().getBubbleWithShortcutId(tileId); + NotificationEntry entry = mNotificationEntryManager.getPendingOrActiveNotif( + notificationKey); + if (mBubble != null || (entry != null && entry.canBubble())) { + mEntryToBubble = entry; + if (DEBUG) { + Log.d(TAG, + "Opening bubble: " + mBubble + ", entry: " + mEntryToBubble); + } + // Just opt-out and don't cancel the notification for bubbles. + finish(); + return; + } } if (mIStatusBarService == null) { 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 39faf5a1eed9..688884730373 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 @@ public class PeopleSpaceWidgetManager { 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 @@ public class PeopleSpaceWidgetManager { "Received updated conversation: " + conversation.getShortcutInfo().getLabel()); } - updateWidgetsWithConversationChanged(conversation); + mBgExecutor.execute(() -> + updateWidgetsWithConversationChanged(conversation)); } } @@ -234,6 +236,10 @@ public class PeopleSpaceWidgetManager { * 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 @@ public class PeopleSpaceWidgetManager { 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 @@ public class PeopleSpaceWidgetManager { 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 @@ public class PeopleSpaceWidgetManager { 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 1010b6a0b97b..14bf8ab78e2c 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 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha 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/QSFooterViewController.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java index f6d93895ce05..a981b6283764 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java @@ -28,6 +28,7 @@ import android.view.View; import android.widget.TextView; import android.widget.Toast; +import com.android.internal.jank.InteractionJankMonitor; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.UiEventLogger; import com.android.internal.logging.nano.MetricsProto; @@ -272,7 +273,8 @@ public class QSFooterViewController extends ViewController<QSFooterView> impleme private void startSettingsActivity() { ActivityLaunchAnimator.Controller animationController = mSettingsButtonContainer != null ? ActivityLaunchAnimator.Controller.fromView( - mSettingsButtonContainer) : null; + mSettingsButtonContainer, + InteractionJankMonitor.CUJ_SHADE_APP_LAUNCH_FROM_SETTINGS_BUTTON) : null; mActivityStarter.startActivity(new Intent(android.provider.Settings.ACTION_SETTINGS), true /* dismissShade */, animationController); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java index e1a66b2c07ee..7b8a6a0a8d0e 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java @@ -539,8 +539,9 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca private void pinToBottom(float absoluteBottomPosition, MediaHost mediaHost, boolean expanded) { View hostView = mediaHost.getHostView(); - // on keyguard we cross-fade to expanded, so no need to pin it. - if (mLastQSExpansion > 0 && !isKeyguardState()) { + // On keyguard we cross-fade to expanded, so no need to pin it. + // If the collapsed qs isn't visible, we also just keep it at the laid out position. + if (mLastQSExpansion > 0 && !isKeyguardState() && mQqsMediaHost.getVisible()) { float targetPosition = absoluteBottomPosition - getTotalBottomMargin(hostView) - hostView.getHeight(); float currentPosition = mediaHost.getCurrentBounds().top diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java index ad4886c5abbe..0bb0a3f7bad4 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java @@ -97,7 +97,7 @@ public class QSPanel extends LinearLayout implements Tunable { private BrightnessMirrorController mBrightnessMirrorController; private LinearLayout mHorizontalLinearLayout; - private LinearLayout mHorizontalContentContainer; + protected LinearLayout mHorizontalContentContainer; // Only used with media private QSTileLayout mHorizontalTileLayout; @@ -132,7 +132,7 @@ public class QSPanel extends LinearLayout implements Tunable { mHorizontalContentContainer = new RemeasuringLinearLayout(mContext); mHorizontalContentContainer.setOrientation(LinearLayout.VERTICAL); - mHorizontalContentContainer.setClipChildren(false); + mHorizontalContentContainer.setClipChildren(true); mHorizontalContentContainer.setClipToPadding(false); mHorizontalTileLayout = createHorizontalTileLayout(); diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java index 9a697b1fe2ce..e24acf27c973 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 @@ public class QuickQSPanel extends QSPanel { } @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 08a68bc8a9a7..997b96626747 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java @@ -266,10 +266,9 @@ public class QuickStatusBarHeader extends FrameLayout { private void updateAlphaAnimator() { TouchAnimator.Builder builder = new TouchAnimator.Builder() - // The following two views have to be hidden manually, so as not to hide the - // Privacy chip in QQS - .addFloat(mDateView, "alpha", 0, 1) .addFloat(mSecurityHeaderView, "alpha", 0, 1) + // These views appear on expanding down + .addFloat(mClockView, "alpha", 0, 1) .addFloat(mQSCarriers, "alpha", 0, 1) .setListener(new TouchAnimator.ListenerAdapter() { @Override @@ -400,12 +399,14 @@ public class QuickStatusBarHeader extends FrameLayout { mClockIconsSeparatorLayoutParams.width = 0; setSeparatorVisibility(false); mShowClockIconsSeparator = false; + mBatteryRemainingIcon.setPercentShowMode(BatteryMeterView.MODE_ESTIMATE); } else { datePrivacySeparatorLayoutParams.width = topCutout.width(); mDatePrivacySeparator.setVisibility(View.VISIBLE); mClockIconsSeparatorLayoutParams.width = topCutout.width(); mShowClockIconsSeparator = true; setSeparatorVisibility(mKeyguardExpansionFraction == 0f); + mBatteryRemainingIcon.setPercentShowMode(BatteryMeterView.MODE_ON); } } mDatePrivacySeparator.setLayoutParams(datePrivacySeparatorLayoutParams); diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java index 1a828e45dc38..cbdcad5cf385 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 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader 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 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader @Override protected void onViewAttached() { - mClockView.setOnClickListener(mOnClickListener); mPrivacyChip.setOnClickListener(mOnClickListener); mMicCameraIndicatorsEnabled = mPrivacyItemController.getMicCameraAvailable(); @@ -188,7 +182,6 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader @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 f56a2bbefaf7..49d18e62346a 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.EXTRA_QS_CUSTOMIZIN 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 @@ public class QSCustomizerController extends ViewController<QSCustomizer> { 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 ba65d5163881..d017c74b4306 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 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta 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 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta 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 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta // 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/tileimpl/QSTileImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java index a938821a343f..894ab528032d 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java @@ -50,6 +50,7 @@ import androidx.lifecycle.LifecycleOwner; import androidx.lifecycle.LifecycleRegistry; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.jank.InteractionJankMonitor; import com.android.internal.logging.InstanceId; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.UiEventLogger; @@ -389,7 +390,8 @@ public abstract class QSTileImpl<TState extends State> implements QSTile, Lifecy */ protected void handleLongClick(@Nullable View view) { ActivityLaunchAnimator.Controller animationController = - view != null ? ActivityLaunchAnimator.Controller.fromView(view) : null; + view != null ? ActivityLaunchAnimator.Controller.fromView(view, + InteractionJankMonitor.CUJ_SHADE_APP_LAUNCH_FROM_QS_TILE) : null; mActivityStarter.postStartActivityDismissingKeyguard(getLongClickIntent(), 0, animationController); } 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 69d49d44f822..73d13700d61b 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/AlarmTile.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AlarmTile.kt @@ -11,6 +11,7 @@ import android.text.TextUtils import android.text.format.DateFormat import android.view.View import androidx.annotation.VisibleForTesting +import com.android.internal.jank.InteractionJankMonitor import com.android.internal.logging.MetricsLogger import com.android.systemui.R import com.android.systemui.animation.ActivityLaunchAnimator @@ -70,7 +71,10 @@ class AlarmTile @Inject constructor( } override fun handleClick(view: View?) { - val animationController = view?.let { ActivityLaunchAnimator.Controller.fromView(it) } + val animationController = view?.let { + ActivityLaunchAnimator.Controller.fromView( + it, InteractionJankMonitor.CUJ_SHADE_APP_LAUNCH_FROM_QS_TILE) + } val pendingIntent = lastAlarmInfo?.showIntent if (pendingIntent != null) { mActivityStarter.postStartActivityDismissingKeyguard(pendingIntent, animationController) diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt index 6d3190ffa725..f66b7226fbae 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt @@ -22,6 +22,7 @@ import android.os.Handler import android.os.Looper import android.service.quicksettings.Tile import android.view.View +import com.android.internal.jank.InteractionJankMonitor import com.android.internal.logging.MetricsLogger import com.android.systemui.R import com.android.systemui.animation.ActivityLaunchAnimator @@ -106,7 +107,8 @@ class DeviceControlsTile @Inject constructor( putExtra(ControlsUiController.EXTRA_ANIMATE, true) } val animationController = view?.let { - ActivityLaunchAnimator.Controller.fromView(it) + ActivityLaunchAnimator.Controller.fromView( + it, InteractionJankMonitor.CUJ_SHADE_APP_LAUNCH_FROM_QS_TILE) } mUiHandler.post { 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 0e4434baa0e8..98cd88af232f 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java @@ -37,6 +37,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.jank.InteractionJankMonitor; import com.android.internal.logging.MetricsLogger; import com.android.systemui.R; import com.android.systemui.animation.ActivityLaunchAnimator; @@ -120,7 +121,8 @@ public class QuickAccessWalletTile extends QSTileImpl<QSTile.State> { @Override protected void handleClick(@Nullable View view) { ActivityLaunchAnimator.Controller animationController = - view == null ? null : ActivityLaunchAnimator.Controller.fromView(view); + view == null ? null : ActivityLaunchAnimator.Controller.fromView(view, + InteractionJankMonitor.CUJ_SHADE_APP_LAUNCH_FROM_QS_TILE); mUiHandler.post(() -> { if (mSelectedCard != null) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java index 32a6c6c20504..24b9208d4ed1 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java @@ -103,6 +103,8 @@ public class ScreenRecordTile extends QSTileImpl<QSTile.BooleanState> state.state = (isRecording || isStarting) ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE; state.label = mContext.getString(R.string.quick_settings_screen_record_label); state.icon = ResourceIcon.get(R.drawable.ic_screenrecord); + // Show expand icon when clicking will open a dialog + state.forceExpandIcon = state.state == Tile.STATE_INACTIVE; if (isRecording) { state.secondaryLabel = mContext.getString(R.string.quick_settings_screen_record_stop); diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java index f4c15fbf90b8..cb0c411b2753 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 @@ public class OverviewProxyService extends CurrentUserTracker implements 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 @@ public class OverviewProxyService extends CurrentUserTracker implements // 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 @@ public class OverviewProxyService extends CurrentUserTracker implements 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 @@ public class OverviewProxyService extends CurrentUserTracker implements 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 @@ public class OverviewProxyService extends CurrentUserTracker implements 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/ActionProxyReceiver.java b/packages/SystemUI/src/com/android/systemui/screenshot/ActionProxyReceiver.java index 17e94c4b3f69..f14044682b61 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ActionProxyReceiver.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ActionProxyReceiver.java @@ -16,6 +16,8 @@ package com.android.systemui.screenshot; +import static android.view.Display.DEFAULT_DISPLAY; + import static com.android.systemui.screenshot.ScreenshotController.ACTION_TYPE_EDIT; import static com.android.systemui.screenshot.ScreenshotController.ACTION_TYPE_SHARE; import static com.android.systemui.screenshot.ScreenshotController.EXTRA_ACTION_INTENT; @@ -30,6 +32,8 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.util.Log; +import android.view.RemoteAnimationAdapter; +import android.view.WindowManagerGlobal; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.statusbar.phone.StatusBar; @@ -69,6 +73,16 @@ public class ActionProxyReceiver extends BroadcastReceiver { intent.getBooleanExtra(EXTRA_DISALLOW_ENTER_PIP, false)); try { actionIntent.send(context, 0, null, null, null, null, opts.toBundle()); + if (intent.getBooleanExtra(ScreenshotController.EXTRA_OVERRIDE_TRANSITION, false)) { + RemoteAnimationAdapter runner = new RemoteAnimationAdapter( + ScreenshotController.SCREENSHOT_REMOTE_RUNNER, 0, 0); + try { + WindowManagerGlobal.getWindowManagerService() + .overridePendingAppTransitionRemote(runner, DEFAULT_DISPLAY); + } catch (Exception e) { + Log.e(TAG, "Error overriding screenshot app transition", e); + } + } } catch (PendingIntent.CanceledException e) { Log.e(TAG, "Pending intent canceled", e); } diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/CropView.java b/packages/SystemUI/src/com/android/systemui/screenshot/CropView.java index 9e11451afa06..0a60f6da159e 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/CropView.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/CropView.java @@ -62,6 +62,7 @@ public class CropView extends View { private final float mCropTouchMargin; private final Paint mShadePaint; private final Paint mHandlePaint; + private final Paint mContainerBackgroundPaint; // Crop rect with each element represented as [0,1] along its proper axis. private RectF mCrop = new RectF(0, 0, 1, 1); @@ -79,6 +80,9 @@ public class CropView extends View { // The allowable values for the current boundary being dragged private Range<Float> mMotionRange; + // Value [0,1] indicating progress in animateEntrance() + private float mEntranceInterpolation = 1f; + private CropInteractionListener mCropInteractionListener; private final ExploreByTouchHelper mExploreByTouchHelper; @@ -92,6 +96,9 @@ public class CropView extends View { attrs, R.styleable.CropView, 0, 0); mShadePaint = new Paint(); mShadePaint.setColor(t.getColor(R.styleable.CropView_scrimColor, Color.TRANSPARENT)); + mContainerBackgroundPaint = new Paint(); + mContainerBackgroundPaint.setColor(t.getColor(R.styleable.CropView_containerBackgroundColor, + Color.TRANSPARENT)); mHandlePaint = new Paint(); mHandlePaint.setColor(t.getColor(R.styleable.CropView_handleColor, Color.BLACK)); mHandlePaint.setStrokeCap(Paint.Cap.ROUND); @@ -125,10 +132,22 @@ public class CropView extends View { @Override public void onDraw(Canvas canvas) { super.onDraw(canvas); - drawShade(canvas, 0, 0, 1, mCrop.top); - drawShade(canvas, 0, mCrop.bottom, 1, 1); + // Top and bottom borders reflect the boundary between the (scrimmed) image and the + // opaque container background. This is only meaningful during an entrance transition. + float topBorder = MathUtils.lerp(mCrop.top, 0, mEntranceInterpolation); + float bottomBorder = MathUtils.lerp(mCrop.bottom, 1, mEntranceInterpolation); + drawShade(canvas, 0, topBorder, 1, mCrop.top); + drawShade(canvas, 0, mCrop.bottom, 1, bottomBorder); drawShade(canvas, 0, mCrop.top, mCrop.left, mCrop.bottom); drawShade(canvas, mCrop.right, mCrop.top, 1, mCrop.bottom); + + // Entrance transition expects the crop bounds to be full width, so we only draw container + // background on the top and bottom. + drawContainerBackground(canvas, 0, 0, 1, topBorder); + drawContainerBackground(canvas, 0, bottomBorder, 1, 1); + + mHandlePaint.setAlpha((int) (mEntranceInterpolation * 255)); + drawHorizontalHandle(canvas, mCrop.top, /* draw the handle tab up */ true); drawHorizontalHandle(canvas, mCrop.bottom, /* draw the handle tab down */ false); drawVerticalHandle(canvas, mCrop.left, /* left */ true); @@ -282,6 +301,22 @@ public class CropView extends View { } /** + * Fade in crop bounds, animate reveal of cropped-out area from current crop bounds. + */ + public void animateEntrance() { + mEntranceInterpolation = 0; + ValueAnimator animator = new ValueAnimator(); + animator.addUpdateListener(animation -> { + mEntranceInterpolation = animation.getAnimatedFraction(); + invalidate(); + }); + animator.setFloatValues(0f, 1f); + animator.setDuration(750); + animator.setInterpolator(new FastOutSlowInInterpolator()); + animator.start(); + } + + /** * Set additional top and bottom padding for the image being cropped (used when the * corresponding ImageView doesn't take the full height). */ @@ -369,6 +404,13 @@ public class CropView extends View { fractionToVerticalPixels(bottom), mShadePaint); } + private void drawContainerBackground(Canvas canvas, float left, float top, float right, + float bottom) { + canvas.drawRect(fractionToHorizontalPixels(left), fractionToVerticalPixels(top), + fractionToHorizontalPixels(right), + fractionToVerticalPixels(bottom), mContainerBackgroundPaint); + } + private void drawHorizontalHandle(Canvas canvas, float frac, boolean handleTabUp) { int y = fractionToVerticalPixels(frac); canvas.drawLine(fractionToHorizontalPixels(mCrop.left), y, diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java b/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java index 30c9b44536e1..25ec1d74008e 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.ComponentName; 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.net.Uri; 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 @@ public class LongScreenshotActivity extends Activity { private ImageView mPreview; private ImageView mTransitionView; + private ImageView mEnterTransitionView; private View mSave; private View mEdit; private View mShare; @@ -111,7 +116,7 @@ public class LongScreenshotActivity extends Activity { 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 @@ public class LongScreenshotActivity extends Activity { 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,9 +190,8 @@ public class LongScreenshotActivity extends Activity { private void onLongScreenshotReceived(LongScreenshot longScreenshot) { Log.d(TAG, "onLongScreenshotReceived(longScreenshot=" + longScreenshot + ")"); mLongScreenshot = longScreenshot; - mPreview.setImageDrawable(mLongScreenshot.getDrawable()); - updateImageDimensions(); - mCropView.setVisibility(View.VISIBLE); + Drawable drawable = mLongScreenshot.getDrawable(); + mPreview.setImageDrawable(drawable); mMagnifierView.setDrawable(mLongScreenshot.getDrawable(), mLongScreenshot.getWidth(), mLongScreenshot.getHeight()); // Original boundaries go from the image tile set's y=0 to y=pageSize, so @@ -196,9 +201,37 @@ public class LongScreenshotActivity extends Activity { 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.setBoundaryPosition( + CropView.CropBoundary.TOP, topFraction); + mCropView.setBoundaryPosition( + CropView.CropBoundary.BOTTOM, bottomFraction); + mCropView.animateEntrance(); + mCropView.setVisibility(View.VISIBLE); + setButtonsEnabled(true); + mEnterTransitionView.setVisibility(View.GONE); + } + }); + } + return true; + } + }); // Immediately export to temp image file for saved state mCacheSaveFuture = mImageExporter.exportAsTempFile(mBackgroundExecutor, @@ -218,6 +251,7 @@ public class LongScreenshotActivity extends Activity { Log.d(TAG, "onCachedImageLoaded(imageResult=" + imageResult + ")"); BitmapDrawable drawable = new BitmapDrawable(getResources(), imageResult.bitmap); mPreview.setImageDrawable(drawable); + mPreview.setAlpha(1f); mMagnifierView.setDrawable(drawable, imageResult.bitmap.getWidth(), imageResult.bitmap.getHeight()); mCropView.setVisibility(View.VISIBLE); @@ -412,22 +446,26 @@ public class LongScreenshotActivity extends Activity { // 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 +477,22 @@ public class LongScreenshotActivity extends Activity { params.width = boundaries.width(); params.height = boundaries.height(); mTransitionView.setLayoutParams(params); + + if (mLongScreenshot != null) { + ConstraintLayout.LayoutParams enterTransitionParams = + (ConstraintLayout.LayoutParams) mEnterTransitionView.getLayoutParams(); + float topFraction = Math.max(0, + -mLongScreenshot.getTop() / (float) mLongScreenshot.getHeight()); + enterTransitionParams.width = (int) (scale * drawable.getIntrinsicWidth()); + enterTransitionParams.height = (int) (scale * mLongScreenshot.getPageHeight()); + mEnterTransitionView.setLayoutParams(enterTransitionParams); + + Matrix matrix = new Matrix(); + matrix.setScale(scale, scale); + matrix.postTranslate(0, -scale * drawable.getIntrinsicHeight() * topFraction); + mEnterTransitionView.setImageMatrix(matrix); + mEnterTransitionView.setTranslationY( + topFraction * previewHeight + mPreview.getPaddingTop() + extraPadding); + } } } diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java b/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java index b5e51c68b76a..e9dea65c2078 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java @@ -319,6 +319,7 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> { .putExtra(ScreenshotController.EXTRA_ID, mScreenshotId) .putExtra(ScreenshotController.EXTRA_SMART_ACTIONS_ENABLED, mSmartActionsEnabled) + .putExtra(ScreenshotController.EXTRA_OVERRIDE_TRANSITION, true) .setAction(Intent.ACTION_EDIT) .addFlags(Intent.FLAG_RECEIVER_FOREGROUND), PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE, diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java index eaa6659790fa..5efa1b2992b2 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; @@ -54,15 +53,18 @@ import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.Message; +import android.os.RemoteException; import android.provider.Settings; import android.util.DisplayMetrics; import android.util.Log; import android.util.Pair; import android.view.Display; import android.view.DisplayAddress; +import android.view.IRemoteAnimationFinishedCallback; +import android.view.IRemoteAnimationRunner; import android.view.KeyEvent; import android.view.LayoutInflater; -import android.view.MotionEvent; +import android.view.RemoteAnimationTarget; import android.view.ScrollCaptureResponse; import android.view.SurfaceControl; import android.view.View; @@ -108,6 +110,31 @@ public class ScreenshotController { private ListenableFuture<ScrollCaptureResponse> mLastScrollCaptureRequest; /** + * This is effectively a no-op, but we need something non-null to pass in, in order to + * successfully override the pending activity entrance animation. + */ + static final IRemoteAnimationRunner.Stub SCREENSHOT_REMOTE_RUNNER = + new IRemoteAnimationRunner.Stub() { + @Override + public void onAnimationStart( + @WindowManager.TransitionOldType int transit, + RemoteAnimationTarget[] apps, + RemoteAnimationTarget[] wallpapers, + RemoteAnimationTarget[] nonApps, + final IRemoteAnimationFinishedCallback finishedCallback) { + try { + finishedCallback.onAnimationFinished(); + } catch (RemoteException e) { + Log.e(TAG, "Error finishing screenshot remote animation", e); + } + } + + @Override + public void onAnimationCancelled() { + } + }; + + /** * POD used in the AsyncTask which saves an image in the background. */ static class SaveImageInBackgroundData { @@ -184,6 +211,7 @@ public class ScreenshotController { static final String ACTION_TYPE_SHARE = "Share"; static final String ACTION_TYPE_EDIT = "Edit"; static final String EXTRA_SMART_ACTIONS_ENABLED = "android:smart_actions_enabled"; + static final String EXTRA_OVERRIDE_TRANSITION = "android:screenshot_override_transition"; static final String EXTRA_ACTION_INTENT = "android:screenshot_action_intent"; static final String SCREENSHOT_URI_ID = "android:screenshot_uri_id"; @@ -289,6 +317,7 @@ public class ScreenshotController { 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 +431,6 @@ public class ScreenshotController { 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 +444,12 @@ public class ScreenshotController { 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 +512,6 @@ public class ScreenshotController { 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 +535,8 @@ public class ScreenshotController { mScreenshotView.reset(); } - int orientation = mContext.getResources().getConfiguration().orientation; - mScreenshotView.updateOrientation(orientation == ORIENTATION_PORTRAIT); + mScreenshotView.updateOrientation(mWindowManager.getCurrentWindowMetrics() + .getWindowInsets().getDisplayCutout()); mScreenBitmap = screenshot; @@ -563,7 +570,9 @@ public class ScreenshotController { // Delay scroll capture eval a bit to allow the underlying activity // to set up in the new orientation. mScreenshotHandler.postDelayed(this::requestScrollCapture, 150); - updateDisplayCutout(); + mScreenshotView.updateDisplayCutoutMargins( + mWindowManager.getCurrentWindowMetrics().getWindowInsets() + .getDisplayCutout()); } }); }); @@ -612,7 +621,7 @@ public class ScreenshotController { // 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 [" @@ -620,6 +629,7 @@ public class ScreenshotController { 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 = @@ -637,9 +647,14 @@ public class ScreenshotController { 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) { @@ -663,7 +678,8 @@ public class ScreenshotController { } @Override - public void onWindowDetached() { } + public void onWindowDetached() { + } }); } @@ -861,24 +877,9 @@ public class ScreenshotController { */ 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(); @@ -964,4 +965,20 @@ public class ScreenshotController { } 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 77e1d154f3ac..2a2217912b58 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.content.res.Resources; 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.Drawable; 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.HorizontalScrollView; 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 @@ public class ScreenshotView extends FrameLayout implements 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 @@ public class ScreenshotView extends FrameLayout implements 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 @@ public class ScreenshotView extends FrameLayout implements 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,17 @@ public class ScreenshotView extends FrameLayout implements }); 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() { @@ -231,6 +257,10 @@ public class ScreenshotView extends FrameLayout implements @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(); @@ -244,15 +274,41 @@ public class ScreenshotView extends FrameLayout implements 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; + } + + 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(); + } + } + }); + } - inoutInfo.touchableRegion.set(touchRegion); + private void stopInputListening() { + if (mInputMonitor != null) { + mInputMonitor.dispose(); + mInputMonitor = null; + } } @Override // ViewGroup @@ -266,6 +322,7 @@ public class ScreenshotView extends FrameLayout implements @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( @@ -279,6 +336,7 @@ public class ScreenshotView extends FrameLayout implements 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)); @@ -307,17 +365,6 @@ public class ScreenshotView extends FrameLayout implements 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(); @@ -327,6 +374,10 @@ public class ScreenshotView extends FrameLayout implements return mScreenshotPreview; } + View getScrollablePreview() { + return mScrollablePreview; + } + /** * Set up the logger and callback on dismissal. * @@ -348,12 +399,35 @@ public class ScreenshotView extends FrameLayout implements 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); @@ -362,6 +436,7 @@ public class ScreenshotView extends FrameLayout implements params.height = screenshotFixedSize; mScreenshotPreview.setScaleType(ImageView.ScaleType.FIT_END); } + mScreenshotPreview.setLayoutParams(params); } @@ -676,6 +751,38 @@ public class ScreenshotView extends FrameLayout implements } } + 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()); } @@ -776,7 +883,7 @@ public class ScreenshotView extends FrameLayout implements transition.action.actionIntent.send(); // fade out non-preview UI - createScreenshotFadeDismissAnimation().start(); + createScreenshotFadeDismissAnimation(false).start(); } catch (PendingIntent.CanceledException e) { mPendingSharedTransition = false; if (transition.onCancelRunnable != null) { @@ -814,7 +921,7 @@ public class ScreenshotView extends FrameLayout implements return animSet; } - private ValueAnimator createScreenshotFadeDismissAnimation() { + ValueAnimator createScreenshotFadeDismissAnimation(boolean fadePreview) { ValueAnimator alphaAnim = ValueAnimator.ofFloat(0, 1); alphaAnim.addUpdateListener(animation -> { float alpha = 1 - animation.getAnimatedFraction(); @@ -822,6 +929,10 @@ public class ScreenshotView extends FrameLayout implements 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 2863074bee0a..94e314948779 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 @@ public class ScrollCaptureClient { 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 b60fd1326cd3..8dd6c8926434 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.FrameLayout; 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 @@ public class BrightnessSliderView extends FrameLayout { 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 @@ public class BrightnessSliderView extends FrameLayout { 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 @@ public class BrightnessSliderView extends FrameLayout { 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/NotificationRemoteInputManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java index ca81a7b43df6..0b67e7eeb132 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 @@ public class NotificationRemoteInputManager implements Dumpable { 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 085a076c5c55..baac2549055f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java @@ -259,11 +259,9 @@ public class NotificationShelf extends ActivatableNotificationView implements final float inShelfAmount = updateShelfTransformation(i, child, scrollingFast, expandingAnimated, isLastChild); - final float stackEnd = mAmbientState.getStackY() - + mAmbientState.getStackHeight(); // TODO(b/172289889) scale mPaddingBetweenElements with expansion amount if ((isLastChild && !child.isInShelf()) || aboveShelf || backgroundForceHidden) { - notificationClipEnd = stackEnd; + notificationClipEnd = shelfStart + getIntrinsicHeight(); } else { notificationClipEnd = shelfStart - mPaddingBetweenElements; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java index 9f59023f1890..f8a1ff879e72 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java @@ -145,11 +145,11 @@ public class StatusBarStateControllerImpl implements SysuiStatusBarStateControll } @Override - public boolean setState(int state) { + public boolean setState(int state, boolean force) { if (state > MAX_STATE || state < MIN_STATE) { throw new IllegalArgumentException("Invalid state " + state); } - if (state == mState) { + if (!force && state == mState) { return false; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SysuiStatusBarStateController.java b/packages/SystemUI/src/com/android/systemui/statusbar/SysuiStatusBarStateController.java index b6d6ed53b681..73f3d90bd4f8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/SysuiStatusBarStateController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/SysuiStatusBarStateController.java @@ -59,7 +59,19 @@ public interface SysuiStatusBarStateController extends StatusBarStateController * @param state see {@link StatusBarState} for valid options * @return {@code true} if the state changed, else {@code false} */ - boolean setState(int state); + default boolean setState(int state) { + return setState(state, false /* force */); + } + + /** + * Update the status bar state + * @param state see {@link StatusBarState} for valid options + * @param force whether to set the state even if it's the same as the current state. This will + * dispatch the state to all StatusBarStateListeners, ensuring that all listening + * components are reset to this state. + * @return {@code true} if the state was changed or set forcefully + */ + boolean setState(int state, boolean force); /** * Update the dozing state from {@link StatusBar}'s perspective diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt index 8479b30c3a75..f30010cf4d1c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt @@ -383,10 +383,18 @@ const val ANIMATING_OUT = 3 const val SHOWING_PERSISTENT_DOT = 4 private const val TAG = "SystemStatusAnimationScheduler" -private const val DELAY: Long = 100 -private const val DISPLAY_LENGTH = 5000L -private const val ENTRANCE_ANIM_LENGTH = 500L -private const val CHIP_ANIM_LENGTH = 500L +private const val DELAY = 0L + +/** + * The total time spent animation should be 1500ms. The entrance animation is how much time + * we give to the system to animate system elements out of the way. Total chip animation length + * will be equivalent to 2*chip_anim_length + display_length + */ +private const val ENTRANCE_ANIM_LENGTH = 250L +private const val CHIP_ANIM_LENGTH = 250L +// 1s + entrance time + chip anim_length +private const val DISPLAY_LENGTH = 1500L + private const val MIN_UPTIME: Long = 5 * 1000 private const val DEBUG = false diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClicker.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClicker.java index aef01e9bd811..0fb1c54bb150 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClicker.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClicker.java @@ -71,11 +71,11 @@ public final class NotificationClicker implements View.OnClickListener { // Check if the notification is displaying the menu, if so slide notification back if (isMenuVisible(row)) { mLogger.logMenuVisible(entry); - row.animateTranslateNotification(0); + row.animateResetTranslation(); return; } else if (row.isChildInGroup() && isMenuVisible(row.getNotificationParent())) { mLogger.logParentMenuVisible(entry); - row.getNotificationParent().animateTranslateNotification(0); + row.getNotificationParent().animateResetTranslation(); return; } else if (row.isSummaryWithChildren() && row.areChildrenExpanded()) { // We never want to open the app directly if the user clicks in between 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 84728f699e91..760bee21b0d1 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 @@ class NotificationWakeUpCoordinator @Inject constructor( } } - private var animatingScreenOff = false - private var collapsedEnoughToHide: Boolean = false var pulsing: Boolean = false @@ -236,11 +234,11 @@ class NotificationWakeUpCoordinator @Inject constructor( } override fun onDozeAmountChanged(linear: Float, eased: Float) { - if (overrideDozeAmountIfBypass()) { + if (overrideDozeAmountIfAnimatingScreenOff(linear)) { return } - if (overrideDozeAmountIfAnimatingScreenOff(linear)) { + if (overrideDozeAmountIfBypass()) { return } @@ -267,7 +265,7 @@ class NotificationWakeUpCoordinator @Inject constructor( 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 @@ class NotificationWakeUpCoordinator @Inject constructor( // dozing) so that the notifications are no longer hidden. setDozeAmount(0f, 0f) } + } + + if (overrideDozeAmountIfAnimatingScreenOff(mLinearDozeAmount)) { + return + } - animatingScreenOff = - state == StatusBarState.SHADE && newState == StatusBarState.KEYGUARD + if (overrideDozeAmountIfBypass()) { + return } - overrideDozeAmountIfBypass() if (bypassController.bypassEnabled && newState == StatusBarState.KEYGUARD && state == StatusBarState.SHADE_LOCKED && (!statusBarStateController.isDozing || shouldAnimateVisibility())) { @@ -330,12 +332,7 @@ class NotificationWakeUpCoordinator @Inject constructor( * 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 @@ class NotificationWakeUpCoordinator @Inject constructor( override fun onDozingChanged(isDozing: Boolean) { if (isDozing) { setNotificationsVisible(visible = false, animate = false, increaseSpeed = false) - } else { - // We only unset the flag once we fully went asleep. If the user interrupts the - // animation in the middle, we have to abort the animation as well to make sure - // the notifications are visible again. - animatingScreenOff = false } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java index 413662447028..c24c2be3faa3 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 @@ -330,30 +330,6 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView } } - @Override - public void setDistanceToTopRoundness(float distanceToTopRoundness) { - super.setDistanceToTopRoundness(distanceToTopRoundness); - mBackgroundNormal.setDistanceToTopRoundness(distanceToTopRoundness); - } - - /** Sets whether this view is the last notification in a section. */ - @Override - public void setLastInSection(boolean lastInSection) { - if (lastInSection != mLastInSection) { - super.setLastInSection(lastInSection); - mBackgroundNormal.setLastInSection(lastInSection); - } - } - - /** Sets whether this view is the first notification in a section. */ - @Override - public void setFirstInSection(boolean firstInSection) { - if (firstInSection != mFirstInSection) { - super.setFirstInSection(firstInSection); - mBackgroundNormal.setFirstInSection(firstInSection); - } - } - /** * Set an override tint color that is used for the background. * diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java index 6fd556763943..ba28dc59def4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java @@ -846,8 +846,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView updateClickAndFocus(); if (mNotificationParent != null) { setOverrideTintColor(NO_COLOR, 0.0f); - // Let's reset the distance to top roundness, as this isn't applied to group children - setDistanceToTopRoundness(NO_ROUNDNESS); mNotificationParent.updateBackgroundForGroupState(); } updateBackgroundClipping(); @@ -876,7 +874,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView @Override protected boolean handleSlideBack() { if (mMenuRow != null && mMenuRow.isMenuVisible()) { - animateTranslateNotification(0 /* targetLeft */); + animateResetTranslation(); return true; } return false; @@ -1713,21 +1711,17 @@ public class ExpandableNotificationRow extends ActivatableNotificationView mChildrenContainer.setContainingNotification(ExpandableNotificationRow.this); mChildrenContainer.onNotificationUpdated(); - if (mShouldTranslateContents) { - mTranslateableViews.add(mChildrenContainer); - } + mTranslateableViews.add(mChildrenContainer); }); - if (mShouldTranslateContents) { - // Add the views that we translate to reveal the menu - mTranslateableViews = new ArrayList<>(); - for (int i = 0; i < getChildCount(); i++) { - mTranslateableViews.add(getChildAt(i)); - } - // Remove views that don't translate - mTranslateableViews.remove(mChildrenContainerStub); - mTranslateableViews.remove(mGutsStub); + // Add the views that we translate to reveal the menu + mTranslateableViews = new ArrayList<>(); + for (int i = 0; i < getChildCount(); i++) { + mTranslateableViews.add(getChildAt(i)); } + // Remove views that don't translate + mTranslateableViews.remove(mChildrenContainerStub); + mTranslateableViews.remove(mGutsStub); } private void doLongClickCallback() { @@ -1805,7 +1799,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView mTranslateAnim.cancel(); } - if (!mShouldTranslateContents) { + if (mDismissUsingRowTranslationX) { setTranslationX(0); } else if (mTranslateableViews != null) { for (int i = 0; i < mTranslateableViews.size(); i++) { @@ -1867,23 +1861,47 @@ public class ExpandableNotificationRow extends ActivatableNotificationView return mPrivateLayout.getActiveRemoteInputText(); } - public void animateTranslateNotification(final float leftTarget) { + /** + * Reset the translation with an animation. + */ + public void animateResetTranslation() { if (mTranslateAnim != null) { mTranslateAnim.cancel(); } - mTranslateAnim = getTranslateViewAnimator(leftTarget, null /* updateListener */); + mTranslateAnim = getTranslateViewAnimator(0, null /* updateListener */); if (mTranslateAnim != null) { mTranslateAnim.start(); } } + /** + * Set the dismiss behavior of the view. + * @param usingRowTranslationX {@code true} if the view should translate using regular + * translationX, otherwise the contents will be + * translated. + */ + @Override + public void setDismissUsingRowTranslationX(boolean usingRowTranslationX) { + if (usingRowTranslationX != mDismissUsingRowTranslationX) { + // In case we were already transitioning, let's switch over! + float previousTranslation = getTranslation(); + if (previousTranslation != 0) { + setTranslation(0); + } + super.setDismissUsingRowTranslationX(usingRowTranslationX); + if (previousTranslation != 0) { + setTranslation(previousTranslation); + } + } + } + @Override public void setTranslation(float translationX) { invalidate(); if (isBlockingHelperShowingAndTranslationFinished()) { mGuts.setTranslationX(translationX); return; - } else if (!mShouldTranslateContents) { + } else if (mDismissUsingRowTranslationX) { setTranslationX(translationX); } else if (mTranslateableViews != null) { // Translate the group of views @@ -1907,7 +1925,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView @Override public float getTranslation() { - if (!mShouldTranslateContents) { + if (mDismissUsingRowTranslationX) { return getTranslationX(); } @@ -2898,7 +2916,11 @@ public class ExpandableNotificationRow extends ActivatableNotificationView float y = event.getY(); NotificationViewWrapper wrapper = getVisibleNotificationViewWrapper(); NotificationHeaderView header = wrapper == null ? null : wrapper.getNotificationHeader(); - if (header != null && header.isInTouchRect(x - getTranslation(), y)) { + // the extra translation only needs to be added, if we're translating the notification + // contents, otherwise the motionEvent is already at the right place due to the + // touch event system. + float translation = !mDismissUsingRowTranslationX ? getTranslation() : 0; + if (header != null && header.isInTouchRect(x - translation, y)) { return true; } if ((!mIsSummaryWithChildren || shouldShowPublic()) @@ -3037,24 +3059,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView } @Override - public boolean topAmountNeedsClipping() { - if (isGroupExpanded()) { - return true; - } - if (isGroupExpansionChanging()) { - return true; - } - if (getShowingLayout().shouldClipToRounding(true /* topRounded */, - false /* bottomRounded */)) { - return true; - } - if (mGuts != null && mGuts.getAlpha() != 0.0f) { - return true; - } - return false; - } - - @Override protected boolean childNeedsClipping(View child) { if (child instanceof NotificationContentView) { NotificationContentView contentView = (NotificationContentView) child; 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 5134c62dc182..d58fe3b3c4a3 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 @@ -71,21 +71,19 @@ public abstract class ExpandableOutlineView extends ExpandableView { private int mBackgroundTop; /** - * {@code true} if the children views of the {@link ExpandableOutlineView} are translated when + * {@code false} if the children views of the {@link ExpandableOutlineView} are translated when * it is moved. Otherwise, the translation is set on the {@code ExpandableOutlineView} itself. */ - protected boolean mShouldTranslateContents; - private boolean mTopAmountRounded; - private float mDistanceToTopRoundness = -1; + protected boolean mDismissUsingRowTranslationX = true; private float[] mTmpCornerRadii = new float[8]; private final ViewOutlineProvider mProvider = new ViewOutlineProvider() { @Override public void getOutline(View view, Outline outline) { if (!mCustomOutline && getCurrentTopRoundness() == 0.0f - && getCurrentBottomRoundness() == 0.0f && !mAlwaysRoundBothCorners - && !mTopAmountRounded) { - int translation = mShouldTranslateContents ? (int) getTranslation() : 0; + && getCurrentBottomRoundness() == 0.0f && !mAlwaysRoundBothCorners) { + // Only when translating just the contents, does the outline need to be shifted. + int translation = !mDismissUsingRowTranslationX ? (int) getTranslation() : 0; int left = Math.max(translation, 0); int top = mClipTopAmount + mBackgroundTop; int right = getWidth() + Math.min(translation, 0); @@ -110,7 +108,9 @@ public abstract class ExpandableOutlineView extends ExpandableView { float topRoundness = mAlwaysRoundBothCorners ? mOutlineRadius : getCurrentBackgroundRadiusTop(); if (!mCustomOutline) { - int translation = mShouldTranslateContents && !ignoreTranslation + // The outline just needs to be shifted if we're translating the contents. Otherwise + // it's already in the right place. + int translation = !mDismissUsingRowTranslationX && !ignoreTranslation ? (int) getTranslation() : 0; int halfExtraWidth = (int) (mExtraWidthForClipping / 2.0f); left = Math.max(translation, 0) - halfExtraWidth; @@ -168,33 +168,15 @@ public abstract class ExpandableOutlineView extends ExpandableView { @Override protected boolean drawChild(Canvas canvas, View child, long drawingTime) { canvas.save(); - Path intersectPath = null; - if (mTopAmountRounded && topAmountNeedsClipping()) { - int left = (int) (- mExtraWidthForClipping / 2.0f); - int top = (int) (mClipTopAmount - mDistanceToTopRoundness); - int right = getWidth() + (int) (mExtraWidthForClipping + left); - int bottom = (int) Math.max(mMinimumHeightForClipping, - Math.max(getActualHeight() - mClipBottomAmount, top + mOutlineRadius)); - getRoundedRectPath(left, top, right, bottom, mOutlineRadius, 0.0f, mClipPath); - intersectPath = mClipPath; - } - boolean clipped = false; if (childNeedsClipping(child)) { Path clipPath = getCustomClipPath(child); if (clipPath == null) { clipPath = getClipPath(false /* ignoreTranslation */); } if (clipPath != null) { - if (intersectPath != null) { - clipPath.op(intersectPath, Path.Op.INTERSECT); - } canvas.clipPath(clipPath); - clipped = true; } } - if (!clipped && intersectPath != null) { - canvas.clipPath(intersectPath); - } boolean result = super.drawChild(canvas, child, drawingTime); canvas.restore(); return result; @@ -212,32 +194,19 @@ public abstract class ExpandableOutlineView extends ExpandableView { invalidate(); } - @Override - public void setDistanceToTopRoundness(float distanceToTopRoundness) { - super.setDistanceToTopRoundness(distanceToTopRoundness); - if (distanceToTopRoundness != mDistanceToTopRoundness) { - mTopAmountRounded = distanceToTopRoundness >= 0; - mDistanceToTopRoundness = distanceToTopRoundness; - applyRoundness(); - } - } - protected boolean childNeedsClipping(View child) { return false; } - public boolean topAmountNeedsClipping() { - return true; - } - protected boolean isClippingNeeded() { - return mAlwaysRoundBothCorners || mCustomOutline || getTranslation() != 0 ; + // When translating the contents instead of the overall view, we need to make sure we clip + // rounded to the contents. + boolean forTranslation = getTranslation() != 0 && !mDismissUsingRowTranslationX; + return mAlwaysRoundBothCorners || mCustomOutline || forTranslation; } private void initDimens() { Resources res = getResources(); - mShouldTranslateContents = - res.getBoolean(R.bool.config_translateNotificationContentsOnSwipe); mOutlineRadius = res.getDimension(R.dimen.notification_shadow_radius); mAlwaysRoundBothCorners = res.getBoolean(R.bool.config_clipNotificationsToOutline); if (!mAlwaysRoundBothCorners) { @@ -272,11 +241,6 @@ public abstract class ExpandableOutlineView extends ExpandableView { } public float getCurrentBackgroundRadiusTop() { - // If this view is top amount notification view, it should always has round corners on top. - // It will be applied with applyRoundness() - if (mTopAmountRounded) { - return mOutlineRadius; - } return getCurrentTopRoundness() * mOutlineRadius; } @@ -382,9 +346,25 @@ public abstract class ExpandableOutlineView extends ExpandableView { } } + /** + * Set the dismiss behavior of the view. + * @param usingRowTranslationX {@code true} if the view should translate using regular + * translationX, otherwise the contents will be + * translated. + */ + public void setDismissUsingRowTranslationX(boolean usingRowTranslationX) { + mDismissUsingRowTranslationX = usingRowTranslationX; + } + @Override public int getOutlineTranslation() { - return mCustomOutline ? mOutlineRect.left : (int) getTranslation(); + if (mCustomOutline) { + return mOutlineRect.left; + } + if (mDismissUsingRowTranslationX) { + return 0; + } + return (int) getTranslation(); } public void updateOutline() { 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 3190927dc24a..8b0764b1c313 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 @@ -46,7 +46,6 @@ import java.util.List; public abstract class ExpandableView extends FrameLayout implements Dumpable { private static final String TAG = "ExpandableView"; - public static final float NO_ROUNDNESS = -1; protected OnHeightChangedListener mOnHeightChangedListener; private int mActualHeight; protected int mClipTopAmount; @@ -192,14 +191,6 @@ public abstract class ExpandableView extends FrameLayout implements Dumpable { } } - /** - * Set the distance to the top roundness, from where we should start clipping a value above - * or equal to 0 is the effective distance, and if a value below 0 is received, there should - * be no clipping. - */ - public void setDistanceToTopRoundness(float distanceToTopRoundness) { - } - public void setActualHeight(int actualHeight) { setActualHeight(actualHeight, true /* notifyListeners */); } @@ -488,7 +479,8 @@ public abstract class ExpandableView extends FrameLayout implements Dumpable { @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/row/FooterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java index 298d4f07a8df..8e24890c8812 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java @@ -115,13 +115,18 @@ public class FooterView extends StackScrollerDecorView { } public class FooterViewState extends ExpandableViewState { + /** + * used to hide the content of the footer to animate. + * #hide is applied without animation, but #hideContent has animation. + */ + public boolean hideContent; + @Override public void applyToView(View view) { super.applyToView(view); if (view instanceof FooterView) { FooterView footerView = (FooterView) view; - boolean visible = this.clipTopAmount < mClearAllTopPadding; - footerView.setContentVisible(visible && footerView.isVisible()); + footerView.setContentVisible(!hideContent); } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java index 4b1f679b8851..754de580cd61 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java @@ -42,10 +42,8 @@ public class NotificationBackgroundView extends View { private int mActualHeight; private int mClipBottomAmount; private int mTintColor; - private float[] mCornerRadii = new float[8]; + private final float[] mCornerRadii = new float[8]; private boolean mBottomIsRounded; - private boolean mLastInSection; - private boolean mFirstInSection; private int mBackgroundTop; private boolean mBottomAmountClips = true; private boolean mExpandAnimationRunning; @@ -53,9 +51,6 @@ public class NotificationBackgroundView extends View { private int mDrawableAlpha = 255; private boolean mIsPressedAllowed; - private boolean mTopAmountRounded; - private float mDistanceToTopRoundness; - public NotificationBackgroundView(Context context, AttributeSet attrs) { super(context, attrs); mDontModifyCorners = getResources().getBoolean( @@ -90,15 +85,6 @@ public class NotificationBackgroundView extends View { left = (int) ((getWidth() - mActualWidth) / 2.0f); right = (int) (left + mActualWidth); } - if (mTopAmountRounded) { - int clipTop = (int) (mClipTopAmount - mDistanceToTopRoundness); - if (clipTop >= 0 || !mFirstInSection) { - top += clipTop; - } - if (clipTop >= 0 && !mLastInSection) { - bottom += clipTop; - } - } drawable.setBounds(left, top, right, bottom); drawable.draw(canvas); } @@ -180,14 +166,6 @@ public class NotificationBackgroundView extends View { invalidate(); } - public void setDistanceToTopRoundness(float distanceToTopRoundness) { - if (distanceToTopRoundness != mDistanceToTopRoundness) { - mTopAmountRounded = distanceToTopRoundness >= 0; - mDistanceToTopRoundness = distanceToTopRoundness; - invalidate(); - } - } - @Override public boolean hasOverlappingRendering() { @@ -246,18 +224,6 @@ public class NotificationBackgroundView extends View { } } - /** Sets whether this background belongs to the last notification in a section. */ - public void setLastInSection(boolean lastInSection) { - mLastInSection = lastInSection; - invalidate(); - } - - /** Sets whether this background belongs to the first notification in a section. */ - public void setFirstInSection(boolean firstInSection) { - mFirstInSection = firstInSection; - invalidate(); - } - private void updateBackgroundRadii() { if (mDontModifyCorners) { return; 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 0c86262d9037..6822d24947c3 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 @@ -75,7 +75,6 @@ public class AmbientState { private int mExpandAnimationTopChange; private ExpandableNotificationRow mExpandingNotification; private float mHideAmount; - private float mNotificationScrimTop; private boolean mAppearing; private float mPulseHeight = MAX_PULSE_HEIGHT; private float mDozeAmount = 0.0f; @@ -256,20 +255,6 @@ public class AmbientState { return mHideAmount; } - /** - * Set y position of top of notifications background scrim, relative to top of screen. - */ - public void setNotificationScrimTop(float notificationScrimTop) { - mNotificationScrimTop = notificationScrimTop; - } - - /** - * @return Y position of top of notifications background scrim, relative to top of screen. - */ - public float getNotificationScrimTop() { - return mNotificationScrimTop; - } - public void setHideSensitive(boolean hideSensitive) { mHideSensitive = hideSensitive; } 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 2c2a17001326..d79c57565dcd 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 @@ -40,6 +40,7 @@ import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Outline; import android.graphics.Paint; +import android.graphics.Path; import android.graphics.PointF; import android.graphics.Rect; import android.os.Bundle; @@ -106,6 +107,7 @@ import com.android.systemui.statusbar.phone.HeadsUpAppearanceController; 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; @@ -423,13 +425,19 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable private final Rect mBackgroundAnimationRect = new Rect(); private ArrayList<BiConsumer<Float, Float>> mExpandedHeightListeners = new ArrayList<>(); private int mHeadsUpInset; + + /** + * The position of the scroll boundary relative to this view. This is where the notifications + * stop scrolling and will start to clip instead. + */ + private int mQsScrollBoundaryPosition; private HeadsUpAppearanceController mHeadsUpAppearanceController; private final Rect mTmpRect = new Rect(); private DismissListener mDismissListener; private DismissAllAnimationListener mDismissAllAnimationListener; private NotificationRemoteInputManager mRemoteInputManager; private ShadeController mShadeController; - private Runnable mOnStackYChanged; + private Consumer<Boolean> mOnStackYChanged; protected boolean mClearAllEnabled; @@ -452,10 +460,43 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable private NotificationStackScrollLayoutController mController; private boolean mKeyguardMediaControllorVisible; + + /** + * The clip path used to clip the view in a rounded way. + */ + private final Path mRoundedClipPath = new Path(); + + /** + * Should we use rounded rect clipping right now + */ + private boolean mShouldUseRoundedRectClipping = false; + + private int mRoundedRectClippingLeft; + private int mRoundedRectClippingTop; + private int mRoundedRectClippingBottom; + private int mRoundedRectClippingRight; + private float[] mBgCornerRadii = new float[8]; + + /** + * Whether stackY should be animated in case the view is getting shorter than the scroll + * position and this scrolling will lead to the top scroll inset getting smaller. + */ + private boolean mAnimateStackYForContentHeightChange = false; + + /** + * Are we launching a notification right now + */ + private boolean mLaunchingNotification; + + /** + * Do notifications dismiss with normal transitioning + */ + private boolean mDismissUsingRowTranslationX = true; private NotificationEntry mTopHeadsUpEntry; private long mNumHeadsUp; private NotificationStackScrollLayoutController.TouchHandler mTouchHandler; private final FeatureFlags mFeatureFlags; + private final UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController; private boolean mShouldUseSplitNotificationShade; private final ExpandableView.OnHeightChangedListener mOnChildHeightChangedListener = @@ -497,12 +538,14 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable GroupMembershipManager groupMembershipManager, GroupExpansionManager groupExpansionManager, AmbientState ambientState, - FeatureFlags featureFlags) { + FeatureFlags featureFlags, + UnlockedScreenOffAnimationController unlockedScreenOffAnimationController) { super(context, attrs, 0, 0); Resources res = getResources(); mSectionsManager = notificationSectionsManager; mFeatureFlags = featureFlags; - mShouldUseSplitNotificationShade = shouldUseSplitNotificationShade(mFeatureFlags, res); + mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController; + updateSplitNotificationShade(); mSectionsManager.initialize(this, LayoutInflater.from(context)); mSections = mSectionsManager.createSectionsForBuckets(); @@ -606,6 +649,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable 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; @@ -857,6 +901,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable mCornerRadius = res.getDimensionPixelSize(R.dimen.notification_corner_radius); mHeadsUpInset = mStatusBarHeight + res.getDimensionPixelSize( R.dimen.heads_up_status_bar_padding); + mQsScrollBoundaryPosition = res.getDimensionPixelSize( + com.android.internal.R.dimen.quick_qs_offset_height); } void updateCornerRadius() { @@ -956,6 +1002,9 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable updateFirstAndLastBackgroundViews(); updateAlgorithmLayoutMinHeight(); updateOwnTranslationZ(); + + // Once the layout has finished, we don't need to animate any scrolling clampings anymore. + mAnimateStackYForContentHeightChange = false; } @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER) @@ -1012,33 +1061,11 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable @ShadeViewRefactor(RefactorComponent.SHADE_VIEW) private void onPreDrawDuringAnimation() { mShelf.updateAppearance(); - updateClippingToTopRoundedCorner(); if (!mNeedsAnimation && !mChildrenUpdateRequested) { updateBackground(); } } - @ShadeViewRefactor(RefactorComponent.SHADE_VIEW) - private void updateClippingToTopRoundedCorner() { - Float clipStart = mAmbientState.getNotificationScrimTop(); - Float clipEnd = clipStart + mCornerRadius; - boolean first = true; - for (int i = 0; i < getChildCount(); i++) { - ExpandableView child = (ExpandableView) getChildAt(i); - if (child.getVisibility() == GONE) { - continue; - } - float start = child.getTranslationY(); - float end = start + child.getActualHeight(); - boolean clip = clipStart > start && clipStart < end - || clipEnd >= start && clipEnd <= end; - clip &= !(first && mScrollAdapter.isScrolledToTop()); - child.setDistanceToTopRoundness(clip ? Math.max(start - clipStart, 0) - : ExpandableView.NO_ROUNDNESS); - first = false; - } - } - @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER) private void updateScrollStateForAddedChildren() { if (mChildrenToAddAnimated.isEmpty()) { @@ -1112,7 +1139,13 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable private void clampScrollPosition() { int scrollRange = getScrollRange(); if (scrollRange < mOwnScrollY) { - setOwnScrollY(scrollRange); + boolean animateStackY = false; + if (scrollRange < getScrollAmountToScrollBoundary() + && mAnimateStackYForContentHeightChange) { + // if the scroll boundary updates the position of the stack, + animateStackY = true; + } + setOwnScrollY(scrollRange, animateStackY); } } @@ -1141,6 +1174,14 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable * Apply expansion fraction to the y position and height of the notifications panel. */ private void updateStackPosition() { + updateStackPosition(false /* listenerNeedsAnimation */); + } + + /** + * Apply expansion fraction to the y position and height of the notifications panel. + * @param listenerNeedsAnimation does the listener need to animate? + */ + private void updateStackPosition(boolean listenerNeedsAnimation) { // Consider interpolating from an mExpansionStartY for use on lockscreen and AOD float endTopPosition = mTopPadding + mExtraTopInsetForFullShadeTransition + mAmbientState.getOverExpansion(); @@ -1148,7 +1189,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable final float stackY = MathUtils.lerp(0, endTopPosition, fraction); mAmbientState.setStackY(stackY); if (mOnStackYChanged != null) { - mOnStackYChanged.run(); + mOnStackYChanged.accept(listenerNeedsAnimation); } if (mQsExpansionFraction <= 0) { final float stackEndHeight = Math.max(0f, @@ -1160,7 +1201,11 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable } } - void setOnStackYChanged(Runnable onStackYChanged) { + /** + * Add a listener when the StackY changes. The argument signifies whether an animation is + * needed. + */ + void setOnStackYChanged(Consumer<Boolean> onStackYChanged) { mOnStackYChanged = onStackYChanged; } @@ -1595,7 +1640,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable protected void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); Resources res = getResources(); - mShouldUseSplitNotificationShade = shouldUseSplitNotificationShade(mFeatureFlags, res); + updateSplitNotificationShade(); mStatusBarHeight = res.getDimensionPixelOffset(R.dimen.status_bar_height); float densityScale = res.getDisplayMetrics().density; mSwipeHelper.setDensityScale(densityScale); @@ -2522,8 +2567,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable updateScrollStateForRemovedChild(child); boolean animationGenerated = generateRemoveAnimation(child); if (animationGenerated) { - if (!mSwipedOutViews.contains(child) - || Math.abs(child.getTranslation()) != child.getWidth()) { + if (!mSwipedOutViews.contains(child) || !isFullySwipedOut(child)) { container.addTransientView(child, 0); child.setTransientContainer(container); } @@ -2535,6 +2579,13 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable focusNextViewIfFocused(child); } + /** + * Has this view been fully swiped out such that it's not visible anymore. + */ + public boolean isFullySwipedOut(ExpandableView child) { + return Math.abs(child.getTranslation()) >= Math.abs(getTotalTranslationLength(child)); + } + @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER) private void focusNextViewIfFocused(View view) { if (view instanceof ExpandableNotificationRow) { @@ -2654,17 +2705,27 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable final int startingPosition = getPositionInLinearLayout(removedChild); final int childHeight = getIntrinsicHeight(removedChild) + mPaddingBetweenElements; final int endPosition = startingPosition + childHeight; - if (endPosition <= mOwnScrollY) { + final int scrollBoundaryStart = getScrollAmountToScrollBoundary(); + mAnimateStackYForContentHeightChange = true; + // This is reset onLayout + if (endPosition <= mOwnScrollY - scrollBoundaryStart) { // This child is fully scrolled of the top, so we have to deduct its height from the // scrollPosition setOwnScrollY(mOwnScrollY - childHeight); - } else if (startingPosition < mOwnScrollY) { + } else if (startingPosition < mOwnScrollY - scrollBoundaryStart) { // This child is currently being scrolled into, set the scroll position to the // start of this child - setOwnScrollY(startingPosition); + setOwnScrollY(startingPosition + scrollBoundaryStart); } } + /** + * @return the amount of scrolling needed to start clipping notifications. + */ + private int getScrollAmountToScrollBoundary() { + return mTopPadding - mQsScrollBoundaryPosition; + } + @ShadeViewRefactor(RefactorComponent.COORDINATOR) private int getIntrinsicHeight(View view) { if (view instanceof ExpandableView) { @@ -2753,7 +2814,10 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable updateAnimationState(child); updateChronometerForChild(child); if (child instanceof ExpandableNotificationRow) { - ((ExpandableNotificationRow) child).setDismissRtl(mDismissRtl); + ExpandableNotificationRow row = (ExpandableNotificationRow) child; + row.setDismissRtl(mDismissRtl); + row.setDismissUsingRowTranslationX(mDismissUsingRowTranslationX); + } } @@ -2813,6 +2877,9 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER) public void applyExpandAnimationParams(ExpandAnimationParameters params) { mAmbientState.setExpandAnimationTopChange(params == null ? 0 : params.getTopChange()); + + // Disable clipping for launches + setLaunchingNotification(params != null); requestChildrenUpdate(); } @@ -2896,7 +2963,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable mAnimationEvents.clear(); updateBackground(); updateViewShadows(); - updateClippingToTopRoundedCorner(); } else { applyCurrentState(); } @@ -3025,7 +3091,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable removedTranslation = row.getTranslationWhenRemoved(); ignoreChildren = false; } - childWasSwipedOut |= Math.abs(row.getTranslation()) == row.getWidth(); + childWasSwipedOut |= isFullySwipedOut(row); } else if (child instanceof MediaHeaderView) { childWasSwipedOut = true; } @@ -3033,11 +3099,11 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable Rect clipBounds = child.getClipBounds(); childWasSwipedOut = clipBounds != null && clipBounds.height() == 0; - if (childWasSwipedOut && child instanceof ExpandableView) { + if (childWasSwipedOut) { // Clean up any potential transient views if the child has already been swiped // out, as we won't be animating it further (due to its height already being // clipped to 0. - ViewGroup transientContainer = ((ExpandableView) child).getTransientContainer(); + ViewGroup transientContainer = child.getTransientContainer(); if (transientContainer != null) { transientContainer.removeTransientView(child); } @@ -3790,6 +3856,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable updateNotificationAnimationStates(); updateChronometers(); requestChildrenUpdate(); + updateUseRoundedRectClipping(); } } @@ -3810,6 +3877,10 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable } void onChildHeightChanged(ExpandableView view, boolean needsAnimation) { + boolean previouslyNeededAnimation = mAnimateStackYForContentHeightChange; + if (needsAnimation) { + mAnimateStackYForContentHeightChange = true; + } updateContentHeight(); updateScrollPositionOnExpandInBottom(view); clampScrollPosition(); @@ -3830,6 +3901,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable requestAnimationOnViewResize(row); } requestChildrenUpdate(); + mAnimateStackYForContentHeightChange = previouslyNeededAnimation; } void onChildHeightReset(ExpandableView view) { @@ -4010,7 +4082,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable setAnimationRunning(false); updateBackground(); updateViewShadows(); - updateClippingToTopRoundedCorner(); } @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER) @@ -4043,7 +4114,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable expandableView.setFakeShadowIntensity( diff / FakeShadowView.SHADOW_SIBLING_TRESHOLD, previous.getOutlineAlpha(), (int) yLocation, - previous.getOutlineTranslation()); + (int) (previous.getOutlineTranslation() + previous.getTranslation())); } previous = expandableView; } @@ -4545,17 +4616,29 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable @ShadeViewRefactor(RefactorComponent.SHADE_VIEW) public void setQsExpansionFraction(float qsExpansionFraction) { mQsExpansionFraction = qsExpansionFraction; + updateUseRoundedRectClipping(); + + // If notifications are scrolled, + // clear out scrollY by the time we push notifications offscreen + if (mOwnScrollY > 0) { + setOwnScrollY((int) MathUtils.lerp(mOwnScrollY, 0, mQsExpansionFraction)); + } } @ShadeViewRefactor(RefactorComponent.COORDINATOR) private void setOwnScrollY(int ownScrollY) { + setOwnScrollY(ownScrollY, false /* animateScrollChangeListener */); + } + + @ShadeViewRefactor(RefactorComponent.COORDINATOR) + private void setOwnScrollY(int ownScrollY, boolean animateStackYChangeListener) { if (ownScrollY != mOwnScrollY) { // We still want to call the normal scrolled changed for accessibility reasons onScrollChanged(mScrollX, ownScrollY, mScrollX, mOwnScrollY); mOwnScrollY = ownScrollY; mAmbientState.setScrollY(mOwnScrollY); updateOnScrollChange(); - updateStackPosition(); + updateStackPosition(animateStackYChangeListener); } } @@ -4617,10 +4700,11 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable @ShadeViewRefactor(RefactorComponent.SHADE_VIEW) @VisibleForTesting - protected void setStatusBarState(int statusBarState) { + public void setStatusBarState(int statusBarState) { mStatusBarState = statusBarState; mAmbientState.setStatusBarState(statusBarState); updateSpeedBumpIndex(); + updateDismissBehavior(); } void onStatePostChange(boolean fromShadeLocked) { @@ -5181,6 +5265,108 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable } /** + * Set rounded rect clipping bounds on this view. + */ + public void setRoundedClippingBounds(int left, int top, int right, int bottom, int topRadius, + int bottomRadius) { + if (mRoundedRectClippingLeft == left && mRoundedRectClippingRight == right + && mRoundedRectClippingBottom == bottom && mRoundedRectClippingTop == top + && mBgCornerRadii[0] == topRadius && mBgCornerRadii[5] == bottomRadius) { + return; + } + mRoundedRectClippingLeft = left; + mRoundedRectClippingTop = top; + mRoundedRectClippingBottom = bottom; + mRoundedRectClippingRight = right; + mBgCornerRadii[0] = topRadius; + mBgCornerRadii[1] = topRadius; + mBgCornerRadii[2] = topRadius; + mBgCornerRadii[3] = topRadius; + mBgCornerRadii[4] = bottomRadius; + mBgCornerRadii[5] = bottomRadius; + mBgCornerRadii[6] = bottomRadius; + mBgCornerRadii[7] = bottomRadius; + mRoundedClipPath.reset(); + mRoundedClipPath.addRoundRect(left, top, right, bottom, mBgCornerRadii, Path.Direction.CW); + if (mShouldUseRoundedRectClipping) { + invalidate(); + } + } + + private void updateSplitNotificationShade() { + boolean split = shouldUseSplitNotificationShade(mFeatureFlags, getResources()); + if (split != mShouldUseSplitNotificationShade) { + mShouldUseSplitNotificationShade = split; + updateDismissBehavior(); + updateUseRoundedRectClipping(); + } + } + + private void updateDismissBehavior() { + // On the split keyguard, dismissing with clipping without a visual boundary looks odd, + // so let's use the content dismiss behavior instead. + boolean dismissUsingRowTranslationX = !mShouldUseSplitNotificationShade + || mStatusBarState != StatusBarState.KEYGUARD; + if (mDismissUsingRowTranslationX != dismissUsingRowTranslationX) { + mDismissUsingRowTranslationX = dismissUsingRowTranslationX; + for (int i = 0; i < getChildCount(); i++) { + View child = getChildAt(i); + if (child instanceof ExpandableNotificationRow) { + ((ExpandableNotificationRow) child).setDismissUsingRowTranslationX( + dismissUsingRowTranslationX); + } + } + } + } + + /** + * Set if we're launching a notification right now. + */ + private void setLaunchingNotification(boolean launching) { + if (launching == mLaunchingNotification) { + return; + } + mLaunchingNotification = launching; + updateUseRoundedRectClipping(); + } + + /** + * Should we use rounded rect clipping + */ + private void updateUseRoundedRectClipping() { + // We don't want to clip notifications when QS is expanded, because incoming heads up on + // the bottom would be clipped otherwise + boolean qsAllowsClipping = mQsExpansionFraction < 0.5f || mShouldUseSplitNotificationShade; + boolean clip = !mLaunchingNotification && mIsExpanded && qsAllowsClipping; + if (clip != mShouldUseRoundedRectClipping) { + mShouldUseRoundedRectClipping = clip; + invalidate(); + } + } + + @Override + protected void dispatchDraw(Canvas canvas) { + if (mShouldUseRoundedRectClipping) { + // Let's clip rounded. + canvas.clipPath(mRoundedClipPath); + } + super.dispatchDraw(canvas); + } + + /** + * Calculate the total translation needed when dismissing. + */ + public float getTotalTranslationLength(View animView) { + if (!mDismissUsingRowTranslationX) { + return animView.getMeasuredWidth(); + } + float notificationWidth = animView.getMeasuredWidth(); + int containerWidth = getMeasuredWidth(); + float padding = (containerWidth - notificationWidth) / 2.0f; + return containerWidth - padding; + } + + /** * 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 dec98887577e..fb4f5592e97f 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 @@ -384,6 +384,11 @@ public class NotificationStackScrollLayoutController { } @Override + public float getTotalTranslationLength(View animView) { + return mView.getTotalTranslationLength(animView); + } + + @Override public void onSnooze(StatusBarNotification sbn, NotificationSwipeActionHelper.SnoozeOption snoozeOption) { mStatusBar.setNotificationSnoozed(sbn, snoozeOption); @@ -822,8 +827,18 @@ public class NotificationStackScrollLayoutController { return mView.isLayoutRtl(); } + /** + * @return the left of the view. + */ public int getLeft() { - return mView.getLeft(); + return mView.getLeft(); + } + + /** + * @return the top of the view. + */ + public int getTop() { + return mView.getTop(); } public float getTranslationX() { @@ -1008,7 +1023,7 @@ public class NotificationStackScrollLayoutController { mView.setQsExpansionFraction(expansionFraction); } - public void setOnStackYChanged(Runnable onStackYChanged) { + public void setOnStackYChanged(Consumer<Boolean> onStackYChanged) { mView.setOnStackYChanged(onStackYChanged); } @@ -1440,6 +1455,14 @@ public class NotificationStackScrollLayoutController { } /** + * Set rounded rect clipping bounds on this view. + */ + public void setRoundedClippingBounds(int left, int top, int right, int bottom, int topRadius, + int bottomRadius) { + mView.setRoundedClippingBounds(left, top, right, bottom, topRadius, bottomRadius); + } + + /** * Enum for UiEvent logged from this class */ enum NotificationPanelEvent implements UiEventLogger.UiEventEnum { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java index f4c4d440b063..664776975b24 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java @@ -325,6 +325,11 @@ class NotificationSwipeHelper extends SwipeHelper implements NotificationSwipeAc } @Override + protected float getTotalTranslationLength(View animView) { + return mCallback.getTotalTranslationLength(animView); + } + + @Override public void setTranslation(View v, float translate) { if (v instanceof SwipeableView) { ((SwipeableView) v).setTranslation(translate); @@ -466,6 +471,13 @@ class NotificationSwipeHelper extends SwipeHelper implements NotificationSwipeAc void onSnooze(StatusBarNotification sbn, SnoozeOption snoozeOption); void onDismiss(); + + /** + * Get the total translation length where we want to swipe to when dismissing the view. By + * default this is the size of the view, but can also be larger. + * @param animView the view to ask about + */ + float getTotalTranslationLength(View animView); } static class Builder { 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 a02ebbfa3521..74e8de4c9d11 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 @@ -158,7 +158,7 @@ public class StackScrollAlgorithm { AmbientState ambientState) { float drawStart = ambientState.isOnKeyguard() ? 0 : ambientState.getStackY() - ambientState.getScrollY(); - float clipStart = ambientState.getNotificationScrimTop(); + float clipStart = 0; int childCount = algorithmState.visibleChildren.size(); boolean firstHeadsUp = true; for (int i = 0; i < childCount; i++) { @@ -411,8 +411,8 @@ public class StackScrollAlgorithm { final float footerEnd = algorithmState.mCurrentExpandedYPosition + view.getIntrinsicHeight(); final boolean noSpaceForFooter = footerEnd > ambientState.getStackEndHeight(); - - viewState.hidden = shadeClosed || isShelfShowing || noSpaceForFooter; + ((FooterView.FooterViewState) viewState).hideContent = + shadeClosed || isShelfShowing || noSpaceForFooter; } else if (view != ambientState.getTrackedHeadsUpRow()) { if (ambientState.isExpansionChanging()) { 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 4fd2064b394d..ee12b4b2d728 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 @@ -392,7 +392,7 @@ public class StackStateAnimator { 0, () -> removeTransientView(changingView), null); } else if (event.animationType == NotificationStackScrollLayout.AnimationEvent.ANIMATION_TYPE_REMOVE_SWIPED_OUT) { - if (Math.abs(changingView.getTranslation()) == changingView.getWidth() + if (mHostLayout.isFullySwipedOut(changingView) && changingView.getTransientContainer() != null) { changingView.getTransientContainer().removeTransientView(changingView); } 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 c911e3d111cf..b5e550a47022 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 @@ public class KeyguardBouncer { 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 class KeyguardBouncer { 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 class KeyguardBouncer { } } + 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 @@ public class KeyguardBouncer { 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 7c2723d724ce..3e4177d32a34 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.content.res.Resources; 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 @@ public class KeyguardClockPositionAlgorithm { 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 @@ public class KeyguardClockPositionAlgorithm { */ private int mUnlockedStackScrollerPadding; - private int mLockScreenMode; - private boolean mIsSplitShade; /** @@ -179,8 +171,8 @@ public class KeyguardClockPositionAlgorithm { */ 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 @@ public class KeyguardClockPositionAlgorithm { mHeight = parentHeight; mKeyguardStatusHeight = keyguardStatusHeight; mUserSwitchHeight = userSwitchHeight; - mClockPreferredY = clockPreferredY; mUserSwitchPreferredY = userSwitchPreferredY; mHasCustomClock = hasCustomClock; mHasVisibleNotifs = hasVisibleNotifs; @@ -228,13 +219,6 @@ public class KeyguardClockPositionAlgorithm { } } - /** - * 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 @@ public class KeyguardClockPositionAlgorithm { } 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 @@ public class KeyguardClockPositionAlgorithm { } 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 @@ public class KeyguardClockPositionAlgorithm { } 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 e2d64b09aee9..35d1526c4c59 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java @@ -101,6 +101,7 @@ import com.android.systemui.fragments.FragmentService; import com.android.systemui.media.KeyguardMediaController; import com.android.systemui.media.MediaDataManager; import com.android.systemui.media.MediaHierarchyManager; +import com.android.systemui.navigationbar.NavigationModeController; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.FalsingManager.FalsingTapListener; import com.android.systemui.plugins.qs.DetailAdapter; @@ -108,6 +109,7 @@ import com.android.systemui.plugins.qs.QS; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener; import com.android.systemui.qs.QSDetailDisplayer; +import com.android.systemui.shared.system.QuickStepContract; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.FeatureFlags; import com.android.systemui.statusbar.GestureRecorder; @@ -254,12 +256,6 @@ public class NotificationPanelViewController extends PanelViewController { new KeyguardUpdateMonitorCallback() { @Override - public void onLockScreenModeChanged(int mode) { - mLockScreenMode = mode; - mClockPositionAlgorithm.onLockScreenModeChanged(mode); - } - - @Override public void onBiometricAuthenticated(int userId, BiometricSourceType biometricSourceType, boolean isStrongBiometric) { @@ -329,7 +325,7 @@ public class NotificationPanelViewController extends PanelViewController { private KeyguardStatusBarView mKeyguardStatusBar; private KeyguardStatusBarViewController mKeyguarStatusBarViewController; private ViewGroup mBigClockContainer; - private QS mQs; + @VisibleForTesting QS mQs; private FrameLayout mQsFrame; private KeyguardStatusViewController mKeyguardStatusViewController; private LockIconViewController mLockIconViewController; @@ -368,7 +364,9 @@ public class NotificationPanelViewController extends PanelViewController { 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; @@ -585,6 +583,11 @@ public class NotificationPanelViewController extends PanelViewController { * The alpha of the views which only show on the keyguard but not in shade / shade locked */ private float mKeyguardOnlyContentAlpha = 1.0f; + + /** + * Are we currently in gesture navigation + */ + private boolean mIsGestureNavigation; private int mOldLayoutDirection; private NotificationShelfController mNotificationShelfController; private int mScrimCornerRadius; @@ -594,7 +597,6 @@ public class NotificationPanelViewController extends PanelViewController { 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() { @@ -674,6 +676,7 @@ public class NotificationPanelViewController extends PanelViewController { KeyguardMediaController keyguardMediaController, PrivacyDotViewController privacyDotViewController, TapAgainViewController tapAgainViewController, + NavigationModeController navigationModeController, FragmentService fragmentService, QuickAccessWalletController quickAccessWalletController, @Main Executor uiExecutor, @@ -774,6 +777,9 @@ public class NotificationPanelViewController extends PanelViewController { mAuthController = authController; mLockIconViewController = lockIconViewController; mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController; + int currentMode = navigationModeController.addListener( + mode -> mIsGestureNavigation = QuickStepContract.isGesturalMode(mode)); + mIsGestureNavigation = QuickStepContract.isGesturalMode(currentMode); mView.setBackgroundColor(Color.TRANSPARENT); OnAttachStateChangeListener onAttachStateChangeListener = new OnAttachStateChangeListener(); @@ -824,6 +830,7 @@ public class NotificationPanelViewController extends PanelViewController { mNotificationStackScrollLayoutController.setOverscrollTopChangedListener( mOnOverscrollTopChangedListener); mNotificationStackScrollLayoutController.setOnScrollListener(this::onNotificationScrolled); + mNotificationStackScrollLayoutController.setOnStackYChanged(this::onStackYChanged); mNotificationStackScrollLayoutController.setOnEmptySpaceClickListener( mOnEmptySpaceClickListener); addTrackingHeadsUpListener(mNotificationStackScrollLayoutController::setTrackingHeadsUp); @@ -1235,7 +1242,6 @@ public class NotificationPanelViewController extends PanelViewController { 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 @@ -1254,12 +1260,9 @@ public class NotificationPanelViewController extends PanelViewController { 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(), @@ -1438,10 +1441,16 @@ public class NotificationPanelViewController extends PanelViewController { 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 @@ -1811,9 +1820,15 @@ public class NotificationPanelViewController extends PanelViewController { } private boolean isInQsArea(float x, float y) { - return (x >= mQsFrame.getX() && x <= mQsFrame.getX() + mQsFrame.getWidth()) && ( - y <= mNotificationStackScrollLayoutController.getBottomMostNotificationBottom() - || y <= mQs.getView().getY() + mQs.getView().getHeight()); + if (x < mQsFrame.getX() || x > mQsFrame.getX() + mQsFrame.getWidth()) { + return false; + } + // Let's reject anything at the very bottom around the home handle in gesture nav + if (mIsGestureNavigation && y > mView.getHeight() - mNavigationBarBottomHeight) { + return false; + } + return y <= mNotificationStackScrollLayoutController.getBottomMostNotificationBottom() + || y <= mQs.getView().getY() + mQs.getView().getHeight(); } private boolean isOpenQsEvent(MotionEvent event) { @@ -2184,26 +2199,31 @@ public class NotificationPanelViewController extends PanelViewController { mDepthController.setQsPanelExpansion(qsExpansionFraction); } - private Runnable mOnStackYChanged = () -> { + private void onStackYChanged(boolean shouldAnimate) { if (mQs != null) { + if (shouldAnimate) { + mAnimateNextNotificationBounds = true; + mNotificationBoundsAnimationDelay = 0; + } setQSClippingBounds(); } }; 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 - updateQSExpansionEnabled(); + updateQSExpansionEnabledAmbient(); } @Override public void setIsShadeOpening(boolean opening) { mAmbientState.setIsShadeOpening(opening); - updateQSExpansionEnabled(); + updateQSExpansionEnabledAmbient(); } - private void updateQSExpansionEnabled() { - setQsExpansionEnabled(mAmbientState.getScrollY() <= 0 && !mAmbientState.isShadeOpening()); + private void updateQSExpansionEnabledAmbient() { + final float scrollRangeToTop = mAmbientState.getTopPadding() - mQuickQsOffsetHeight; + mQsExpansionEnabledAmbient = + mAmbientState.getScrollY() <= scrollRangeToTop && !mAmbientState.isShadeOpening(); + setQsExpansionEnabled(); } /** @@ -2211,14 +2231,13 @@ public class NotificationPanelViewController extends PanelViewController { * and QS state. */ private void setQSClippingBounds() { - int top = 0; - int bottom = 0; - int left = 0; - int right = 0; + int top; + int bottom; + int left; + int right; final int qsPanelBottomY = calculateQsBottomPosition(computeQsExpansionFraction()); - final boolean visible = (computeQsExpansionFraction() > 0 || qsPanelBottomY > 0) - && !mShouldUseSplitNotificationShade; + final boolean qsVisible = (computeQsExpansionFraction() > 0 || qsPanelBottomY > 0); if (!mShouldUseSplitNotificationShade) { if (mTransitioningToFullShadeProgress > 0.0f) { @@ -2227,7 +2246,6 @@ public class NotificationPanelViewController extends PanelViewController { top = mTransitionToFullShadeQSPosition; } else { final float notificationTop = getQSEdgePosition(); - mAmbientState.setNotificationScrimTop(notificationTop); top = (int) (isOnKeyguard() ? Math.min(qsPanelBottomY, notificationTop) : notificationTop); } @@ -2235,8 +2253,7 @@ public class NotificationPanelViewController extends PanelViewController { // notification bounds should take full screen width regardless of insets left = 0; right = getView().getRight() + mDisplayRightInset; - } else if (qsPanelBottomY > 0) { // so bounds are empty on lockscreen - mAmbientState.setNotificationScrimTop(mSplitShadeNotificationsTopPadding); + } else { top = Math.min(qsPanelBottomY, mSplitShadeNotificationsTopPadding); bottom = mNotificationStackScrollLayoutController.getHeight(); left = mNotificationStackScrollLayoutController.getLeft(); @@ -2244,17 +2261,17 @@ public class NotificationPanelViewController extends PanelViewController { } // top should never be lower than bottom, otherwise it will be invisible. top = Math.min(top, bottom); - applyQSClippingBounds(left, top, right, bottom, visible); + applyQSClippingBounds(left, top, right, bottom, qsVisible); } private void applyQSClippingBounds(int left, int top, int right, int bottom, - boolean visible) { + boolean qsVisible) { if (!mAnimateNextNotificationBounds || mKeyguardStatusAreaClipBounds.isEmpty()) { if (mQsClippingAnimation != null) { // update the end position of the animator mQsClippingAnimationEndBounds.set(left, top, right, bottom); } else { - applyQSClippingImmediately(left, top, right, bottom, visible); + applyQSClippingImmediately(left, top, right, bottom, qsVisible); } } else { mQsClippingAnimationEndBounds.set(left, top, right, bottom); @@ -2278,7 +2295,7 @@ public class NotificationPanelViewController extends PanelViewController { int animBottom = (int) MathUtils.lerp(startBottom, mQsClippingAnimationEndBounds.bottom, fraction); applyQSClippingImmediately(animLeft, animTop, animRight, animBottom, - visible /* visible */); + qsVisible /* qsVisible */); }); mQsClippingAnimation.addListener(new AnimatorListenerAdapter() { @Override @@ -2293,7 +2310,7 @@ public class NotificationPanelViewController extends PanelViewController { } private void applyQSClippingImmediately(int left, int top, int right, int bottom, - boolean visible) { + boolean qsVisible) { // Fancy clipping for quick settings int radius = mScrimCornerRadius; int statusBarClipTop = 0; @@ -2301,19 +2318,34 @@ public class NotificationPanelViewController extends PanelViewController { if (!mShouldUseSplitNotificationShade) { // The padding on this area is large enough that we can use a cheaper clipping strategy mKeyguardStatusAreaClipBounds.set(left, top, right, bottom); - clipStatusView = visible; + clipStatusView = qsVisible; radius = (int) MathUtils.lerp(mScreenCornerRadius, mScrimCornerRadius, Math.min(top / (float) mScrimCornerRadius, 1f)); statusBarClipTop = top - mKeyguardStatusBar.getTop(); } if (mQs != null) { - mQs.setFancyClipping(top, bottom, radius, visible); + mQs.setFancyClipping(top, bottom, radius, qsVisible + && !mShouldUseSplitNotificationShade); } mKeyguardStatusViewController.setClipBounds( clipStatusView ? mKeyguardStatusAreaClipBounds : null); - mScrimController.setNotificationsBounds(left, top, right, bottom); + if (!qsVisible && mShouldUseSplitNotificationShade) { + // On the lockscreen when qs isn't visible, we don't want the bounds of the shade to + // be visible, otherwise you can see the bounds once swiping up to see bouncer + mScrimController.setNotificationsBounds(0, 0, 0, 0); + } else { + mScrimController.setNotificationsBounds(left, top, right, bottom); + } + mScrimController.setScrimCornerRadius(radius); mKeyguardStatusBar.setTopClipping(statusBarClipTop); + int nsslLeft = left - mNotificationStackScrollLayoutController.getLeft(); + int nsslRight = right - mNotificationStackScrollLayoutController.getLeft(); + int nsslTop = top - mNotificationStackScrollLayoutController.getTop(); + int nsslBottom = bottom - mNotificationStackScrollLayoutController.getTop(); + int bottomRadius = mShouldUseSplitNotificationShade ? radius : 0; + mNotificationStackScrollLayoutController.setRoundedClippingBounds( + nsslLeft, nsslTop, nsslRight, nsslBottom, radius, bottomRadius); } private float getQSEdgePosition() { @@ -2535,7 +2567,9 @@ public class NotificationPanelViewController extends PanelViewController { break; case FLING_HIDE: default: - mQs.closeDetail(); + if (mQs != null) { + mQs.closeDetail(); + } target = 0; } if (target == mQsExpansionHeight) { @@ -3304,7 +3338,6 @@ public class NotificationPanelViewController extends PanelViewController { // The expandedHeight is always the full panel Height when bypassing expandedHeight = getMaxPanelHeightNonBypass(); } - mNotificationStackScrollLayoutController.setOnStackYChanged(mOnStackYChanged); mNotificationStackScrollLayoutController.setExpandedHeight(expandedHeight); updateKeyguardBottomAreaAlpha(); updateBigClockAlpha(); @@ -3595,11 +3628,6 @@ public class NotificationPanelViewController extends PanelViewController { * security view of the bouncer. */ public void onBouncerPreHideAnimation() { - mKeyguardStatusViewController.setKeyguardStatusViewVisibility( - mBarState, - true /* keyguardFadingAway */, - false /* goingToFullShade */, - mBarState); if (mKeyguardQsUserSwitchController != null) { mKeyguardQsUserSwitchController.setKeyguardQsUserSwitchVisibility( mBarState, @@ -4283,7 +4311,8 @@ public class NotificationPanelViewController extends PanelViewController { /** * 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); 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 1331829201b8..7a1e5cf1770b 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 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump 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 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump } 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 09779d12f7b3..07ad1368da25 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 @@ public class StatusBar extends SystemUI implements DemoMode, && ((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 @@ public class StatusBar extends SystemUI implements DemoMode, 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,12 +2109,6 @@ public class StatusBar extends SystemUI implements DemoMode, @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; - } - // We post to the main thread for 2 reasons: // 1. KeyguardViewMediator is not thread-safe. // 2. To ensure that ViewMediatorCallback#keyguardDonePending is called before @@ -2846,12 +2837,15 @@ public class StatusBar extends SystemUI implements DemoMode, @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()); + boolean animate = + animationController != null && !willLaunchResolverActivity && shouldAnimateLaunch( + true /* isActivityIntent */); ActivityLaunchAnimator.Controller animController = - shouldAnimateLaunch(true /* isActivityIntent */) ? wrapAnimationController( - animationController, dismissShade) : null; + animate ? 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. @@ -2865,7 +2859,7 @@ public class StatusBar extends SystemUI implements DemoMode, int[] result = new int[]{ActivityManager.START_CANCELED}; mActivityLaunchAnimator.startIntentWithAnimation(animController, - true /* animate */, intent.getPackage(), (adapter) -> { + animate, intent.getPackage(), (adapter) -> { ActivityOptions options = new ActivityOptions( getActivityOptions(mDisplayId, adapter)); options.setDisallowEnterPictureInPictureWhileLaunching( @@ -2915,16 +2909,12 @@ public class StatusBar extends SystemUI implements DemoMode, } }; executeRunnableDismissingKeyguard(runnable, cancelRunnable, dismissShadeDirectly, - afterKeyguardGone, true /* deferred */); + willLaunchResolverActivity, true /* deferred */, animate); } @Nullable private ActivityLaunchAnimator.Controller wrapAnimationController( - @Nullable ActivityLaunchAnimator.Controller animationController, boolean dismissShade) { - if (animationController == null) { - return null; - } - + ActivityLaunchAnimator.Controller animationController, boolean dismissShade) { View rootView = animationController.getLaunchContainer().getRootView(); if (rootView == mSuperStatusBarViewFactory.getStatusBarWindowView()) { // We are animating a view in the status bar. We have to make sure that the status bar @@ -2967,34 +2957,56 @@ public class StatusBar extends SystemUI implements DemoMode, final boolean dismissShade, final boolean afterKeyguardGone, final boolean deferred) { - dismissKeyguardThenExecute(() -> { - if (runnable != null) { - if (mStatusBarKeyguardViewManager.isShowing() - && mStatusBarKeyguardViewManager.isOccluded()) { - mStatusBarKeyguardViewManager.addAfterKeyguardGoneRunnable(runnable); - } else { - AsyncTask.execute(runnable); - } - } - if (dismissShade) { - if (mExpandedVisible && !mBouncerShowing) { - mShadeController.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, - true /* force */, true /* delayed*/); - } else { + executeRunnableDismissingKeyguard(runnable, cancelAction, dismissShade, afterKeyguardGone, + deferred, false /* willAnimateOnKeyguard */); + } - // Do it after DismissAction has been processed to conserve the needed ordering. - mHandler.post(mShadeController::runPostCollapseRunnables); + public void executeRunnableDismissingKeyguard(final Runnable runnable, + final Runnable cancelAction, + final boolean dismissShade, + final boolean afterKeyguardGone, + final boolean deferred, + final boolean willAnimateOnKeyguard) { + OnDismissAction onDismissAction = new OnDismissAction() { + @Override + public boolean onDismiss() { + if (runnable != null) { + if (mStatusBarKeyguardViewManager.isShowing() + && mStatusBarKeyguardViewManager.isOccluded()) { + mStatusBarKeyguardViewManager.addAfterKeyguardGoneRunnable(runnable); + } else { + AsyncTask.execute(runnable); + } } - } else if (isInLaunchTransition() - && mNotificationPanelViewController.isLaunchTransitionFinished()) { + if (dismissShade) { + if (mExpandedVisible && !mBouncerShowing) { + mShadeController.animateCollapsePanels( + CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, + true /* force */, true /* delayed*/); + } else { + + // Do it after DismissAction has been processed to conserve the needed + // ordering. + mHandler.post(mShadeController::runPostCollapseRunnables); + } + } else if (StatusBar.this.isInLaunchTransition() + && mNotificationPanelViewController.isLaunchTransitionFinished()) { + + // We are not dismissing the shade, but the launch transition is already + // finished, + // so nobody will call readyForKeyguardDone anymore. Post it such that + // keyguardDonePending gets called first. + mHandler.post(mStatusBarKeyguardViewManager::readyForKeyguardDone); + } + return deferred; + } - // We are not dismissing the shade, but the launch transition is already finished, - // so nobody will call readyForKeyguardDone anymore. Post it such that - // keyguardDonePending gets called first. - mHandler.post(mStatusBarKeyguardViewManager::readyForKeyguardDone); + @Override + public boolean willRunAnimationOnKeyguard() { + return willAnimateOnKeyguard; } - return deferred; - }, cancelAction, afterKeyguardGone); + }; + dismissKeyguardThenExecute(onDismissAction, cancelAction, afterKeyguardGone); } private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { @@ -3416,6 +3428,10 @@ public class StatusBar extends SystemUI implements DemoMode, } boolean updateIsKeyguard() { + return updateIsKeyguard(false /* force */); + } + + boolean updateIsKeyguard(boolean force) { boolean wakeAndUnlocking = mBiometricUnlockController.getMode() == BiometricUnlockController.MODE_WAKE_AND_UNLOCK; @@ -3439,7 +3455,7 @@ public class StatusBar extends SystemUI implements DemoMode, showKeyguardImpl(); } } else { - return hideKeyguardImpl(); + return hideKeyguardImpl(force); } return false; } @@ -3521,10 +3537,10 @@ public class StatusBar extends SystemUI implements DemoMode, public void fadeKeyguardWhilePulsing() { mNotificationPanelViewController.fadeOut(0, FADE_KEYGUARD_DURATION_PULSING, ()-> { - hideKeyguard(); if (shouldShowCircleReveal()) { startCircleReveal(); } + hideKeyguard(); mStatusBarKeyguardViewManager.onKeyguardFadedAway(); }).start(); } @@ -3568,11 +3584,11 @@ public class StatusBar extends SystemUI implements DemoMode, /** * @return true if we would like to stay in the shade, false if it should go away entirely */ - public boolean hideKeyguardImpl() { + public boolean hideKeyguardImpl(boolean force) { mIsKeyguard = false; Trace.beginSection("StatusBar#hideKeyguard"); boolean staying = mStatusBarStateController.leaveOpenOnKeyguardHide(); - if (!(mStatusBarStateController.setState(StatusBarState.SHADE))) { + if (!(mStatusBarStateController.setState(StatusBarState.SHADE, force))) { //TODO: StatusBarStateController should probably know about hiding the keyguard and // notify listeners. @@ -3882,9 +3898,7 @@ public class StatusBar extends SystemUI implements DemoMode, 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)) { @@ -4460,7 +4474,6 @@ public class StatusBar extends SystemUI implements DemoMode, } else { mScrimController.transitionTo(ScrimState.UNLOCKED, mUnlockScrimCallback); } - updateLightRevealScrimVisibility(); Trace.endSection(); } @@ -4620,27 +4633,37 @@ public class StatusBar extends SystemUI implements DemoMode, * * @param action The action to execute after dismissing the keyguard. * @param collapsePanel Whether we should collapse the panel after dismissing the keyguard. + * @param willAnimateOnKeyguard Whether {@param action} will run an animation on the keyguard if + * we are locked. */ private void executeActionDismissingKeyguard(Runnable action, boolean afterKeyguardGone, - boolean collapsePanel) { + boolean collapsePanel, boolean willAnimateOnKeyguard) { if (!mDeviceProvisionedController.isDeviceProvisioned()) return; - dismissKeyguardThenExecute(() -> { - new Thread(() -> { - try { - // The intent we are sending is for the application, which - // won't have permission to immediately start an activity after - // the user switches to home. We know it is safe to do at this - // point, so make sure new activity switches are now allowed. - ActivityManager.getService().resumeAppSwitches(); - } catch (RemoteException e) { - } - action.run(); - }).start(); + OnDismissAction onDismissAction = new OnDismissAction() { + @Override + public boolean onDismiss() { + new Thread(() -> { + try { + // The intent we are sending is for the application, which + // won't have permission to immediately start an activity after + // the user switches to home. We know it is safe to do at this + // point, so make sure new activity switches are now allowed. + ActivityManager.getService().resumeAppSwitches(); + } catch (RemoteException e) { + } + action.run(); + }).start(); - boolean deferred = collapsePanel ? mShadeController.collapsePanel() : false; - return deferred; - }, afterKeyguardGone); + return collapsePanel ? mShadeController.collapsePanel() : willAnimateOnKeyguard; + } + + @Override + public boolean willRunAnimationOnKeyguard() { + return willAnimateOnKeyguard; + } + }; + dismissKeyguardThenExecute(onDismissAction, afterKeyguardGone); } @Override @@ -4672,12 +4695,18 @@ public class StatusBar extends SystemUI implements DemoMode, 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; executeActionDismissingKeyguard(() -> { try { // We wrap animationCallback with a StatusBarLaunchAnimatorController so that the @@ -4706,7 +4735,7 @@ public class StatusBar extends SystemUI implements DemoMode, if (intentSentUiThreadCallback != null) { postOnUiThread(intentSentUiThreadCallback); } - }, afterKeyguardGone, collapse); + }, willLaunchResolverActivity, collapse, animate); } private void postOnUiThread(Runnable runnable) { @@ -4895,15 +4924,9 @@ public class StatusBar extends SystemUI implements DemoMode, 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 29bb1f4ac7c6..2601b8b14e1d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -192,6 +192,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb private OnDismissAction mAfterKeyguardGoneAction; private Runnable mKeyguardGoneCancelAction; + private boolean mDismissActionWillAnimateOnKeyguard; private final ArrayList<Runnable> mAfterKeyguardGoneRunnables = new ArrayList<>(); // Dismiss action to be launched when we stop dozing or the keyguard is gone. @@ -447,7 +448,17 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb mAfterKeyguardGoneAction = r; mKeyguardGoneCancelAction = cancelAction; + mDismissActionWillAnimateOnKeyguard = r != null && r.willRunAnimationOnKeyguard(); + + // 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(); } @@ -615,6 +626,13 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb if (mBouncer.isShowing()) { mBouncer.startPreHideAnimation(finishRunnable); mStatusBar.onBouncerPreHideAnimation(); + + // We update the state (which will show the keyguard) only if an animation will run on + // the keyguard. If there is no animation, we wait before updating the state so that we + // go directly from bouncer to launcher/app. + if (mDismissActionWillAnimateOnKeyguard) { + updateStates(); + } } else if (finishRunnable != null) { finishRunnable.run(); } @@ -785,6 +803,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb mAfterKeyguardGoneAction = null; } mKeyguardGoneCancelAction = null; + mDismissActionWillAnimateOnKeyguard = false; for (int i = 0; i < mAfterKeyguardGoneRunnables.size(); i++) { mAfterKeyguardGoneRunnables.get(i).run(); } @@ -853,6 +872,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb return; // allow bouncer to trigger saved actions } mAfterKeyguardGoneAction = null; + mDismissActionWillAnimateOnKeyguard = false; if (mKeyguardGoneCancelAction != null) { mKeyguardGoneCancelAction.run(); mKeyguardGoneCancelAction = null; 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 7b7c17d08eda..98b9cc9bc716 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java @@ -41,6 +41,7 @@ import android.text.TextUtils; import android.util.EventLog; import android.view.View; +import com.android.internal.jank.InteractionJankMonitor; import com.android.internal.logging.MetricsLogger; import com.android.internal.statusbar.NotificationVisibility; import com.android.internal.widget.LockPatternUtils; @@ -252,23 +253,33 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit } 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()); - ActivityStarter.OnDismissAction postKeyguardAction = - () -> handleNotificationClickAfterKeyguardDismissed( + ActivityStarter.OnDismissAction postKeyguardAction = new ActivityStarter.OnDismissAction() { + @Override + public boolean onDismiss() { + return handleNotificationClickAfterKeyguardDismissed( entry, row, controller, intent, isActivityIntent, animate, showOverLockscreen); + } + + @Override + public boolean willRunAnimationOnKeyguard() { + return animate; + } + }; if (showOverLockscreen) { mIsCollapsingToShowActivityOverLockscreen = true; postKeyguardAction.onDismiss(); } else { mActivityStarter.dismissKeyguardThenExecute( - postKeyguardAction, null /* cancel */, afterKeyguardGone); + postKeyguardAction, null /* cancel */, willLaunchResolverActivity); } } @@ -296,7 +307,9 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit } else { runnable.run(); } - return !mNotificationPanel.isFullyCollapsed(); + + // Always defer the keyguard dismiss when animating. + return animate || !mNotificationPanel.isFullyCollapsed(); } private void handleNotificationClickAfterPanelCollapsed( @@ -450,53 +463,76 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit public void startNotificationGutsIntent(final Intent intent, final int appUid, ExpandableNotificationRow row) { boolean animate = mStatusBar.shouldAnimateLaunch(true /* isActivityIntent */); - mActivityStarter.dismissKeyguardThenExecute(() -> { - AsyncTask.execute(() -> { - ActivityLaunchAnimator.Controller animationController = - new StatusBarLaunchAnimatorController( - mNotificationAnimationProvider.getAnimatorController(row), - mStatusBar, true /* isActivityIntent */); - - mActivityLaunchAnimator.startIntentWithAnimation( - animationController, animate, intent.getPackage(), - (adapter) -> TaskStackBuilder.create(mContext) - .addNextIntentWithParentStack(intent) - .startActivities(getActivityOptions( - mStatusBar.getDisplayId(), - adapter), - new UserHandle(UserHandle.getUserId(appUid)))); - }); - return true; - }, null, false /* afterKeyguardGone */); + ActivityStarter.OnDismissAction onDismissAction = new ActivityStarter.OnDismissAction() { + @Override + public boolean onDismiss() { + AsyncTask.execute(() -> { + ActivityLaunchAnimator.Controller animationController = + new StatusBarLaunchAnimatorController( + mNotificationAnimationProvider.getAnimatorController(row), + mStatusBar, true /* isActivityIntent */); + + mActivityLaunchAnimator.startIntentWithAnimation( + animationController, animate, intent.getPackage(), + (adapter) -> TaskStackBuilder.create(mContext) + .addNextIntentWithParentStack(intent) + .startActivities(getActivityOptions( + mStatusBar.getDisplayId(), + adapter), + new UserHandle(UserHandle.getUserId(appUid)))); + }); + return true; + } + + @Override + public boolean willRunAnimationOnKeyguard() { + return animate; + } + }; + mActivityStarter.dismissKeyguardThenExecute(onDismissAction, null, + false /* afterKeyguardGone */); } @Override public void startHistoryIntent(View view, boolean showHistory) { boolean animate = mStatusBar.shouldAnimateLaunch(true /* isActivityIntent */); - mActivityStarter.dismissKeyguardThenExecute(() -> { - AsyncTask.execute(() -> { - Intent intent = showHistory ? new Intent( - Settings.ACTION_NOTIFICATION_HISTORY) : new Intent( - Settings.ACTION_NOTIFICATION_SETTINGS); - TaskStackBuilder tsb = TaskStackBuilder.create(mContext) - .addNextIntent(new Intent(Settings.ACTION_NOTIFICATION_SETTINGS)); - if (showHistory) { - tsb.addNextIntent(intent); - } + ActivityStarter.OnDismissAction onDismissAction = new ActivityStarter.OnDismissAction() { + @Override + public boolean onDismiss() { + AsyncTask.execute(() -> { + Intent intent = showHistory ? new Intent( + Settings.ACTION_NOTIFICATION_HISTORY) : new Intent( + Settings.ACTION_NOTIFICATION_SETTINGS); + TaskStackBuilder tsb = TaskStackBuilder.create(mContext) + .addNextIntent(new Intent(Settings.ACTION_NOTIFICATION_SETTINGS)); + if (showHistory) { + tsb.addNextIntent(intent); + } - ActivityLaunchAnimator.Controller animationController = - new StatusBarLaunchAnimatorController( - ActivityLaunchAnimator.Controller.fromView(view), mStatusBar, - true /* isActivityIntent */); + ActivityLaunchAnimator.Controller viewController = + ActivityLaunchAnimator.Controller.fromView(view, + InteractionJankMonitor.CUJ_SHADE_APP_LAUNCH_FROM_HISTORY_BUTTON + ); + ActivityLaunchAnimator.Controller animationController = + new StatusBarLaunchAnimatorController(viewController, mStatusBar, + true /* isActivityIntent */); + + mActivityLaunchAnimator.startIntentWithAnimation(animationController, animate, + intent.getPackage(), + (adapter) -> tsb.startActivities( + getActivityOptions(mStatusBar.getDisplayId(), adapter), + UserHandle.CURRENT)); + }); + return true; + } - mActivityLaunchAnimator.startIntentWithAnimation(animationController, animate, - intent.getPackage(), - (adapter) -> tsb.startActivities( - getActivityOptions(mStatusBar.getDisplayId(), adapter), - UserHandle.CURRENT)); - }); - return true; - }, null, false /* afterKeyguardGone */); + @Override + public boolean willRunAnimationOnKeyguard() { + return animate; + } + }; + mActivityStarter.dismissKeyguardThenExecute(onDismissAction, null, + false /* afterKeyguardGone */); } private void removeHunAfterClick(ExpandableNotificationRow row) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt index e135cc51a7bc..a2d0672e6812 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt @@ -131,9 +131,14 @@ class UnlockedScreenOffAnimationController @Inject constructor( lightRevealAnimationPlaying = false aodUiAnimationPlaying = false - // Make sure the status bar is in the correct keyguard state, since we might have left it in - // the KEYGUARD state if this wakeup cancelled the screen off animation. - statusBar.updateIsKeyguard() + // Make sure the status bar is in the correct keyguard state, forcing it if necessary. This + // is required if the screen off animation is cancelled, since it might be incorrectly left + // in the KEYGUARD or SHADE states depending on when it was cancelled and whether 'lock + // instantly' is enabled. We need to force it so that the state is set even if we're going + // from SHADE to SHADE or KEYGUARD to KEYGUARD, since we might have changed parts of the UI + // (such as showing AOD in the shade) without actually changing the StatusBarState. This + // ensures that the UI definitely reflects the desired state. + statusBar.updateIsKeyguard(true /* force */) } override fun onStartedGoingToSleep() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt index ef7fac311799..b295f6659f81 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt @@ -25,6 +25,7 @@ import android.content.Intent import android.util.Log import android.view.View import android.widget.Chronometer +import com.android.internal.jank.InteractionJankMonitor import com.android.systemui.R import com.android.systemui.animation.ActivityLaunchAnimator import com.android.systemui.dagger.SysUISingleton @@ -179,7 +180,10 @@ class OngoingCallController @Inject constructor( logger.logChipClicked() activityStarter.postStartActivityDismissingKeyguard( currentCallNotificationInfo.intent, 0, - ActivityLaunchAnimator.Controller.fromView(backgroundView)) + ActivityLaunchAnimator.Controller.fromView( + backgroundView, + InteractionJankMonitor.CUJ_STATUS_BAR_APP_LAUNCH_FROM_CALL_CHIP) + ) } setUpUidObserver(currentCallNotificationInfo) 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 7563b3082ed8..3b272da837d9 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.ControlsServiceInfo 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 @@ public class DeviceControlsControllerImpl @Inject constructor( 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/KeyguardQsUserSwitchController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchController.java index 2ecd4b3db5a1..1f1817cd29f0 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 @@ public class KeyguardQsUserSwitchController extends ViewController<UserAvatarVie 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 68f2a62a4fec..43b2061ecd32 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 @@ public class KeyguardUserSwitcherController extends ViewController<KeyguardUserS 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/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java index 4ab07af92006..24604849a776 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java @@ -796,6 +796,9 @@ public class NetworkControllerImpl extends BroadcastReceiver for (int i = 0; i < mMobileSignalControllers.size(); i++) { MobileSignalController controller = mMobileSignalControllers.valueAt(i); controller.setConfiguration(mConfig); + if (mProviderModel) { + controller.refreshCallIndicator(mCallbackHandler); + } } refreshLocale(); } 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 7022fb13d2cd..efeeac669491 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 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene 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 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene 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 af1284459d63..143ba06747d3 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 @@ public class WalletControllerImpl @Inject constructor( 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 b9b62b415c00..753def0b0f1c 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 @@ public class WifiSignalController extends @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/ThemeOverlayController.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java index 428921ee34ec..ca1f55e95ff4 100644 --- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java +++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java @@ -240,11 +240,14 @@ public class ThemeOverlayController extends SystemUI implements Dumpable { 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."); @@ -326,17 +329,22 @@ public class ThemeOverlayController extends SystemUI implements Dumpable { 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/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java index 961822a598e7..407b248cee44 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java @@ -151,12 +151,12 @@ public class VolumeDialogImpl implements VolumeDialog, private final int mDialogShowAnimationDurationMs; private final int mDialogHideAnimationDurationMs; - private final int mDialogWidth; - private final int mDialogCornerRadius; - private final int mRingerDrawerItemSize; - private final int mRingerRowsPadding; - private final boolean mShowVibrate; - private final int mRingerCount; + private int mDialogWidth; + private int mDialogCornerRadius; + private int mRingerDrawerItemSize; + private int mRingerRowsPadding; + private boolean mShowVibrate; + private int mRingerCount; private final boolean mShowLowMediaVolumeIcon; private final boolean mChangeVolumeRowTintWhenInactive; @@ -288,18 +288,8 @@ public class VolumeDialogImpl implements VolumeDialog, mDialogRowsView.invalidate(); }; } - mDialogWidth = mContext.getResources().getDimensionPixelSize( - R.dimen.volume_dialog_panel_width); - mDialogCornerRadius = mContext.getResources().getDimensionPixelSize( - R.dimen.volume_dialog_panel_width_half); - mRingerDrawerItemSize = mContext.getResources().getDimensionPixelSize( - R.dimen.volume_ringer_drawer_item_size); - mRingerRowsPadding = mContext.getResources().getDimensionPixelSize( - R.dimen.volume_dialog_ringer_rows_padding); - mShowVibrate = mController.hasVibrator(); - // Normal, mute, and possibly vibrate. - mRingerCount = mShowVibrate ? 3 : 2; + initDimens(); } @Override @@ -378,6 +368,8 @@ public class VolumeDialogImpl implements VolumeDialog, private void initDialog() { mDialog = new CustomDialog(mContext); + initDimens(); + mConfigurableTexts = new ConfigurableTexts(mContext); mHovering = false; mShowing = false; @@ -569,6 +561,21 @@ public class VolumeDialogImpl implements VolumeDialog, initODICaptionsH(); } + private void initDimens() { + mDialogWidth = mContext.getResources().getDimensionPixelSize( + R.dimen.volume_dialog_panel_width); + mDialogCornerRadius = mContext.getResources().getDimensionPixelSize( + R.dimen.volume_dialog_panel_width_half); + mRingerDrawerItemSize = mContext.getResources().getDimensionPixelSize( + R.dimen.volume_ringer_drawer_item_size); + mRingerRowsPadding = mContext.getResources().getDimensionPixelSize( + R.dimen.volume_dialog_ringer_rows_padding); + mShowVibrate = mController.hasVibrator(); + + // Normal, mute, and possibly vibrate. + mRingerCount = mShowVibrate ? 3 : 2; + } + protected ViewGroup getDialogView() { return mDialogView; } @@ -932,6 +939,13 @@ public class VolumeDialogImpl implements VolumeDialog, .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; } @@ -976,6 +990,11 @@ public class VolumeDialogImpl implements VolumeDialog, .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; } @@ -1464,20 +1483,8 @@ public class VolumeDialogImpl implements VolumeDialog, } 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); @@ -1487,6 +1494,18 @@ public class VolumeDialogImpl implements VolumeDialog, }); } + 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/wmshell/BubblesManager.java b/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java index 10c4a55ad240..5441bd4c958d 100644 --- a/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java +++ b/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java @@ -84,6 +84,7 @@ import com.android.systemui.statusbar.phone.ScrimController; import com.android.systemui.statusbar.phone.ShadeController; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.ZenModeController; +import com.android.wm.shell.bubbles.Bubble; import com.android.wm.shell.bubbles.BubbleEntry; import com.android.wm.shell.bubbles.Bubbles; @@ -657,6 +658,22 @@ public class BubblesManager implements Dumpable { mBubbles.expandStackAndSelectBubble(notifToBubbleEntry(entry)); } + /** + * Request the stack expand if needed, then select the specified Bubble as current. + * + * @param bubble the bubble to be selected + */ + public void expandStackAndSelectBubble(Bubble bubble) { + mBubbles.expandStackAndSelectBubble(bubble); + } + + /** + * @return a bubble that matches the provided shortcutId, if one exists. + */ + public Bubble getBubbleWithShortcutId(String shortcutId) { + return mBubbles.getBubbleWithShortcutId(shortcutId); + } + /** See {@link NotifCallback}. */ public void addNotifCallback(NotifCallback callback) { mCallbacks.add(callback); diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java index 0342796817c3..3d4da270dd44 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java @@ -62,7 +62,6 @@ import android.nfc.NfcAdapter; import android.os.Bundle; import android.os.Handler; import android.os.IRemoteCallback; -import android.os.PowerManager; import android.os.UserHandle; import android.os.UserManager; import android.telephony.ServiceState; @@ -166,8 +165,6 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { @Mock private AuthController mAuthController; @Mock - private PowerManager mPowerManager; - @Mock private TelephonyListenerManager mTelephonyListenerManager; @Mock private FeatureFlags mFeatureFlags; @@ -526,46 +523,6 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { } @Test - public void testFingerprintCancelAodInterrupt_onAuthenticationFailed() { - // GIVEN on keyguard and listening for fingerprint authentication - mKeyguardUpdateMonitor.dispatchStartedGoingToSleep(0 /* why */); - mTestableLooper.processAllMessages(); - - ArgumentCaptor<FingerprintManager.AuthenticationCallback> fingerprintCallbackCaptor = - ArgumentCaptor.forClass(FingerprintManager.AuthenticationCallback.class); - verify(mFingerprintManager).authenticate(any(), any(), fingerprintCallbackCaptor.capture(), - any(), anyInt(), anyInt()); - FingerprintManager.AuthenticationCallback authCallback = - fingerprintCallbackCaptor.getValue(); - - // WHEN authentication fails - authCallback.onAuthenticationFailed(); - - // THEN aod interrupt is cancelled - verify(mAuthController).onCancelUdfps(); - } - - @Test - public void testFingerprintCancelAodInterrupt_onAuthenticationError() { - // GIVEN on keyguard and listening for fingerprint authentication - mKeyguardUpdateMonitor.dispatchStartedGoingToSleep(0 /* why */); - mTestableLooper.processAllMessages(); - - ArgumentCaptor<FingerprintManager.AuthenticationCallback> fingerprintCallbackCaptor = - ArgumentCaptor.forClass(FingerprintManager.AuthenticationCallback.class); - verify(mFingerprintManager).authenticate(any(), any(), fingerprintCallbackCaptor.capture(), - any(), anyInt(), anyInt()); - FingerprintManager.AuthenticationCallback authCallback = - fingerprintCallbackCaptor.getValue(); - - // WHEN authentication errors - authCallback.onAuthenticationError(0, ""); - - // THEN aod interrupt is cancelled - verify(mAuthController).onCancelUdfps(); - } - - @Test public void skipsAuthentication_whenStatusBarShadeLocked() { mStatusBarStateListener.onStateChanged(StatusBarState.SHADE_LOCKED); mKeyguardUpdateMonitor.dispatchStartedWakingUp(); @@ -1022,7 +979,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { mBroadcastDispatcher, mDumpManager, mRingerModeTracker, mBackgroundExecutor, mStatusBarStateController, mLockPatternUtils, - mAuthController, mTelephonyListenerManager, mPowerManager, mFeatureFlags); + mAuthController, mTelephonyListenerManager, mFeatureFlags); setStrongAuthTracker(KeyguardUpdateMonitorTest.this.mStrongAuthTracker); } diff --git a/packages/SystemUI/tests/src/com/android/keyguard/TextAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/TextAnimatorTest.kt index ad7f0cbe1e3a..3322414e9e7a 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 @@ package com.android.keyguard 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 @@ class TextAnimatorTest : SysuiTestCase() { 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 149e179de5a6..e42d537596c5 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 @@ package com.android.keyguard 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.android.systemui.SysuiTestCase 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 BIDI_TEXT = "abc\u05D0\u05D1\u05D2" 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/MagnificationModeSwitchTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java index 485df21656d3..5617f1b6316b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java @@ -59,7 +59,6 @@ import android.os.UserHandle; import android.provider.Settings; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; -import android.util.MathUtils; import android.view.Choreographer; import android.view.MotionEvent; import android.view.View; @@ -489,20 +488,20 @@ public class MagnificationModeSwitchTest extends SysuiTestCase { @Test public void onRotationChanged_buttonIsShowing_expectedYPosition() { final Rect windowBounds = mWindowManager.getCurrentWindowMetrics().getBounds(); - final int oldWindowHeight = windowBounds.height(); mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); + final Rect oldDraggableBounds = new Rect(mMagnificationModeSwitch.mDraggableWindowBounds); final float windowHeightFraction = - (float) mWindowManager.getLayoutParamsFromAttachedView().y / oldWindowHeight; + (float) (mWindowManager.getLayoutParamsFromAttachedView().y + - oldDraggableBounds.top) / oldDraggableBounds.height(); - // The window bounds are changed due to the rotation change. + // The window bounds and the draggable bounds are changed due to the rotation change. final Rect newWindowBounds = new Rect(0, 0, windowBounds.height(), windowBounds.width()); mWindowManager.setWindowBounds(newWindowBounds); mMagnificationModeSwitch.onConfigurationChanged(ActivityInfo.CONFIG_ORIENTATION); - int expectedY = (int) (newWindowBounds.height() * windowHeightFraction); - expectedY = MathUtils.constrain(expectedY, - mMagnificationModeSwitch.mDraggableWindowBounds.top, - mMagnificationModeSwitch.mDraggableWindowBounds.bottom); + int expectedY = (int) (windowHeightFraction + * mMagnificationModeSwitch.mDraggableWindowBounds.height()) + + mMagnificationModeSwitch.mDraggableWindowBounds.top; assertEquals( "The Y position does not keep the same height ratio after the rotation changed.", expectedY, mWindowManager.getLayoutParamsFromAttachedView().y); diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java index 724f8a3adf80..d6226aa53f67 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java @@ -73,6 +73,7 @@ public class DozeConfigurationUtil { when(config.dozePickupSensorAvailable()).thenReturn(false); when(config.wakeScreenGestureAvailable()).thenReturn(false); when(config.quickPickupSensorEnabled(anyInt())).thenReturn(false); + when(config.screenOffUdfpsEnabled(anyInt())).thenReturn(false); doneHolder[0] = true; return config; 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 4a9d66c16003..c0b45c6d5c96 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 class DozeTriggersTest extends SysuiTestCase { 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/globalactions/GlobalActionsDialogLiteTest.java b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java index 83e7b17eb746..f0f5420b2531 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java @@ -38,8 +38,9 @@ import android.os.UserManager; import android.service.dreams.IDreamManager; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; +import android.view.GestureDetector; import android.view.IWindowManager; -import android.view.View; +import android.view.MotionEvent; import android.view.WindowManagerPolicyConstants; import androidx.test.filters.SmallTest; @@ -57,6 +58,7 @@ import com.android.systemui.plugins.GlobalActions; import com.android.systemui.settings.UserContextProvider; import com.android.systemui.statusbar.NotificationShadeDepthController; import com.android.systemui.statusbar.NotificationShadeWindowController; +import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.telephony.TelephonyListenerManager; @@ -109,6 +111,7 @@ public class GlobalActionsDialogLiteTest extends SysuiTestCase { @Mock private SysUiState mSysUiState; @Mock private Handler mHandler; @Mock private UserContextProvider mUserContextProvider; + @Mock private StatusBar mStatusBar; private TestableLooper mTestableLooper; @@ -150,7 +153,8 @@ public class GlobalActionsDialogLiteTest extends SysuiTestCase { mInfoProvider, mRingerModeTracker, mSysUiState, - mHandler + mHandler, + mStatusBar ); mGlobalActionsDialogLite.setZeroDialogPressDelayForTesting(); @@ -194,7 +198,7 @@ public class GlobalActionsDialogLiteTest extends SysuiTestCase { } @Test - public void testShouldLogOnTapOutside() { + public void testSingleTap_logAndDismiss() { mGlobalActionsDialogLite = spy(mGlobalActionsDialogLite); doReturn(4).when(mGlobalActionsDialogLite).getMaxShownPowerItems(); doReturn(true).when(mGlobalActionsDialogLite).shouldDisplayLockdown(any()); @@ -207,9 +211,58 @@ public class GlobalActionsDialogLiteTest extends SysuiTestCase { }; doReturn(actions).when(mGlobalActionsDialogLite).getDefaultActions(); GlobalActionsDialogLite.ActionsDialogLite dialog = mGlobalActionsDialogLite.createDialog(); - View container = dialog.findViewById(com.android.systemui.R.id.global_actions_container); - container.callOnClick(); + + GestureDetector.SimpleOnGestureListener gestureListener = spy(dialog.mGestureListener); + gestureListener.onSingleTapConfirmed(null); + verifyLogPosted(GlobalActionsDialog.GlobalActionsEvent.GA_CLOSE_TAP_OUTSIDE); + } + + @Test + public void testSwipeDownLockscreen_logAndOpenQS() { + mGlobalActionsDialogLite = spy(mGlobalActionsDialogLite); + doReturn(4).when(mGlobalActionsDialogLite).getMaxShownPowerItems(); + doReturn(true).when(mGlobalActionsDialogLite).shouldDisplayLockdown(any()); + doReturn(true).when(mGlobalActionsDialogLite).shouldShowAction(any()); + doReturn(true).when(mStatusBar).isKeyguardShowing(); + String[] actions = { + GlobalActionsDialog.GLOBAL_ACTION_KEY_EMERGENCY, + GlobalActionsDialog.GLOBAL_ACTION_KEY_LOCKDOWN, + GlobalActionsDialog.GLOBAL_ACTION_KEY_POWER, + GlobalActionsDialog.GLOBAL_ACTION_KEY_RESTART, + }; + doReturn(actions).when(mGlobalActionsDialogLite).getDefaultActions(); + GlobalActionsDialogLite.ActionsDialogLite dialog = mGlobalActionsDialogLite.createDialog(); + + GestureDetector.SimpleOnGestureListener gestureListener = spy(dialog.mGestureListener); + MotionEvent start = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 0, 0); + MotionEvent end = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 500, 0); + gestureListener.onFling(start, end, 0, 1000); + verifyLogPosted(GlobalActionsDialog.GlobalActionsEvent.GA_CLOSE_TAP_OUTSIDE); + verify(mStatusBar).animateExpandSettingsPanel(null); + } + + @Test + public void testSwipeDown_logAndOpenNotificationShade() { + mGlobalActionsDialogLite = spy(mGlobalActionsDialogLite); + doReturn(4).when(mGlobalActionsDialogLite).getMaxShownPowerItems(); + doReturn(true).when(mGlobalActionsDialogLite).shouldDisplayLockdown(any()); + doReturn(true).when(mGlobalActionsDialogLite).shouldShowAction(any()); + doReturn(false).when(mStatusBar).isKeyguardShowing(); + String[] actions = { + GlobalActionsDialog.GLOBAL_ACTION_KEY_EMERGENCY, + GlobalActionsDialog.GLOBAL_ACTION_KEY_LOCKDOWN, + GlobalActionsDialog.GLOBAL_ACTION_KEY_POWER, + GlobalActionsDialog.GLOBAL_ACTION_KEY_RESTART, + }; + doReturn(actions).when(mGlobalActionsDialogLite).getDefaultActions(); + GlobalActionsDialogLite.ActionsDialogLite dialog = mGlobalActionsDialogLite.createDialog(); + + GestureDetector.SimpleOnGestureListener gestureListener = spy(dialog.mGestureListener); + MotionEvent start = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 0, 0); + MotionEvent end = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 500, 0); + gestureListener.onFling(start, end, 0, 1000); verifyLogPosted(GlobalActionsDialog.GlobalActionsEvent.GA_CLOSE_TAP_OUTSIDE); + verify(mStatusBar).animateExpandNotificationsPanel(); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java index 3130e977dc83..c54347063487 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java @@ -65,6 +65,7 @@ import com.android.systemui.plugins.GlobalActionsPanelPlugin; import com.android.systemui.settings.UserTracker; import com.android.systemui.statusbar.NotificationShadeDepthController; import com.android.systemui.statusbar.NotificationShadeWindowController; +import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.telephony.TelephonyListenerManager; @@ -124,6 +125,7 @@ public class GlobalActionsDialogTest extends SysuiTestCase { @Mock private Handler mHandler; @Mock private UserTracker mUserTracker; @Mock private SecureSettings mSecureSettings; + @Mock private StatusBar mStatusBar; private TestableLooper mTestableLooper; @@ -164,7 +166,8 @@ public class GlobalActionsDialogTest extends SysuiTestCase { mUiEventLogger, mRingerModeTracker, mSysUiState, - mHandler + mHandler, + mStatusBar ); mGlobalActionsDialog.setZeroDialogPressDelayForTesting(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/people/widget/LaunchConversationActivityTest.java b/packages/SystemUI/tests/src/com/android/systemui/people/widget/LaunchConversationActivityTest.java index ccb40e116115..f6264ffc6a70 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/people/widget/LaunchConversationActivityTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/people/widget/LaunchConversationActivityTest.java @@ -16,11 +16,14 @@ package com.android.systemui.people.widget; +import static android.view.Display.DEFAULT_DISPLAY; + import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -39,11 +42,14 @@ import androidx.test.filters.SmallTest; import com.android.internal.statusbar.IStatusBarService; import com.android.internal.statusbar.NotificationVisibility; import com.android.systemui.SysuiTestCase; +import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.wmshell.BubblesManager; +import com.android.wm.shell.bubbles.Bubble; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; @@ -87,6 +93,8 @@ public class LaunchConversationActivityTest extends SysuiTestCase { @Mock private UserManager mUserManager; + private CommandQueue mCommandQueue; + @Captor private ArgumentCaptor<NotificationVisibility> mNotificationVisibilityCaptor; @@ -95,8 +103,9 @@ public class LaunchConversationActivityTest extends SysuiTestCase { @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); + mCommandQueue = new CommandQueue(mContext); mActivity = new LaunchConversationActivity(mNotificationEntryManager, - Optional.of(mBubblesManager), mUserManager); + Optional.of(mBubblesManager), mUserManager, mCommandQueue); mActivity.setIsForTesting(true, mIStatusBarService); mIntent = new Intent(); mIntent.putExtra(PeopleSpaceWidgetProvider.EXTRA_TILE_ID, "tile ID"); @@ -159,9 +168,13 @@ public class LaunchConversationActivityTest extends SysuiTestCase { mActivity.setIntent(mIntent); mActivity.onCreate(new Bundle()); + assertThat(mActivity.isFinishing()).isTrue(); + mCommandQueue.appTransitionFinished(DEFAULT_DISPLAY); + verify(mIStatusBarService, times(1)).onNotificationClear(any(), anyInt(), any(), anyInt(), anyInt(), mNotificationVisibilityCaptor.capture()); - verify(mBubblesManager, never()).expandStackAndSelectBubble(any()); + verify(mBubblesManager, never()).expandStackAndSelectBubble(any(Bubble.class)); + verify(mBubblesManager, never()).expandStackAndSelectBubble(any(NotificationEntry.class)); NotificationVisibility nv = mNotificationVisibilityCaptor.getValue(); assertThat(nv.count).isEqualTo(NOTIF_COUNT); @@ -175,6 +188,9 @@ public class LaunchConversationActivityTest extends SysuiTestCase { mActivity.setIntent(mIntent); mActivity.onCreate(new Bundle()); + assertThat(mActivity.isFinishing()).isTrue(); + mCommandQueue.appTransitionFinished(DEFAULT_DISPLAY); + // Don't clear the notification for bubbles. verify(mIStatusBarService, never()).onNotificationClear(any(), anyInt(), any(), anyInt(), anyInt(), any()); @@ -190,8 +206,28 @@ public class LaunchConversationActivityTest extends SysuiTestCase { mActivity.onCreate(new Bundle()); assertThat(mActivity.isFinishing()).isTrue(); + mCommandQueue.appTransitionFinished(DEFAULT_DISPLAY); + verify(mIStatusBarService, never()).onNotificationClear(any(), anyInt(), any(), anyInt(), anyInt(), any()); - verify(mBubblesManager, never()).expandStackAndSelectBubble(any()); + verify(mBubblesManager, never()).expandStackAndSelectBubble(any(Bubble.class)); + verify(mBubblesManager, never()).expandStackAndSelectBubble(any(NotificationEntry.class)); + } + + @Ignore + @Test + public void testBubbleWithNoNotifOpensBubble() throws Exception { + Bubble bubble = mock(Bubble.class); + when(mBubblesManager.getBubbleWithShortcutId(any())).thenReturn(bubble); + + mIntent.putExtra(PeopleSpaceWidgetProvider.EXTRA_NOTIFICATION_KEY, + EMPTY_STRING); + mActivity.setIntent(mIntent); + mActivity.onCreate(new Bundle()); + + assertThat(mActivity.isFinishing()).isTrue(); + mCommandQueue.appTransitionFinished(DEFAULT_DISPLAY); + + verify(mBubblesManager, times(1)).expandStackAndSelectBubble(eq(bubble)); } } 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 46a60dc47e7b..7af374308bef 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 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase { 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 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase { 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 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase { 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 3c1b36e41d89..7ac6f8212a61 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 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() { } @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/ScreenRecordTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java index e4af21aa7cd4..3b4e863ed8bd 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java @@ -19,6 +19,7 @@ package com.android.systemui.qs.tiles; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertTrue; +import static org.junit.Assert.assertFalse; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -167,4 +168,37 @@ public class ScreenRecordTileTest extends SysuiTestCase { assertTrue(mTile.getState().contentDescription.toString().contains(mTile.getState().label)); } + + @Test + public void testForceExpandIcon_notRecordingNotStarting() { + when(mController.isStarting()).thenReturn(false); + when(mController.isRecording()).thenReturn(false); + + mTile.refreshState(); + mTestableLooper.processAllMessages(); + + assertTrue(mTile.getState().forceExpandIcon); + } + + @Test + public void testForceExpandIcon_recordingNotStarting() { + when(mController.isStarting()).thenReturn(false); + when(mController.isRecording()).thenReturn(true); + + mTile.refreshState(); + mTestableLooper.processAllMessages(); + + assertFalse(mTile.getState().forceExpandIcon); + } + + @Test + public void testForceExpandIcon_startingNotRecording() { + when(mController.isStarting()).thenReturn(true); + when(mController.isRecording()).thenReturn(false); + + mTile.refreshState(); + mTestableLooper.processAllMessages(); + + assertFalse(mTile.getState().forceExpandIcon); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java index 2e0827f24bf8..fa25c3f1e005 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java @@ -289,6 +289,7 @@ public class ExpandableNotificationRowTest extends SysuiTestCase { @Test public void testIconScrollXAfterTranslationAndReset() throws Exception { + mGroupRow.setDismissUsingRowTranslationX(false); mGroupRow.setTranslation(50); assertEquals(50, -mGroupRow.getEntry().getIcons().getShelfIcon().getScrollX()); 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 8758e1609fa8..43f7284e477e 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.row.FooterView; 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 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { @Mock private NotificationSwipeHelper mNotificationSwipeHelper; @Mock private NotificationStackScrollLayoutController mStackScrollLayoutController; @Mock private FeatureFlags mFeatureFlags; + @Mock private UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController; @Before @UiThreadTest @@ -143,7 +145,8 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { 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 152ba90858d6..226c4668ba55 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 @@ import org.junit.runner.RunWith; 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 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase { 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 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase { 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 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase { 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 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase { } @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 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase { 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 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase { } @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 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase { 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 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase { 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 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase { 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 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase { // 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 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase { 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 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase { // 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 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase { 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 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase { } @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 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase { 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 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase { 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 4b5657afe02f..2d51683c8ae5 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 @@ -82,6 +82,7 @@ import com.android.systemui.fragments.FragmentService; import com.android.systemui.media.KeyguardMediaController; import com.android.systemui.media.MediaDataManager; import com.android.systemui.media.MediaHierarchyManager; +import com.android.systemui.navigationbar.NavigationModeController; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.qs.QSDetailDisplayer; import com.android.systemui.statusbar.CommandQueue; @@ -129,6 +130,8 @@ import java.util.List; @TestableLooper.RunWithLooper public class NotificationPanelViewTest extends SysuiTestCase { + private static final int NOTIFICATION_SCRIM_TOP_PADDING_IN_SPLIT_SHADE = 50; + @Mock private StatusBar mStatusBar; @Mock @@ -258,6 +261,8 @@ public class NotificationPanelViewTest extends SysuiTestCase { @Mock private PrivacyDotViewController mPrivacyDotViewController; @Mock + private NavigationModeController mNavigationModeController; + @Mock private SecureSettings mSecureSettings; @Mock private TapAgainViewController mTapAgainViewController; @@ -290,6 +295,8 @@ public class NotificationPanelViewTest extends SysuiTestCase { 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()); @@ -386,6 +393,7 @@ public class NotificationPanelViewTest extends SysuiTestCase { mKeyguardMediaController, mPrivacyDotViewController, mTapAgainViewController, + mNavigationModeController, mFragmentService, mQuickAccessWalletController, new FakeExecutor(new FakeSystemClock()), 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 deff2043f6dc..154972e135bd 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 @@ public class StatusBarTest extends SysuiTestCase { 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 @@ public class StatusBarTest extends SysuiTestCase { 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); @@ -843,12 +843,14 @@ public class StatusBarTest extends SysuiTestCase { // By default, showKeyguardImpl sets state to KEYGUARD. mStatusBar.showKeyguardImpl(); - verify(mStatusBarStateController).setState(eq(StatusBarState.KEYGUARD)); + verify(mStatusBarStateController).setState( + eq(StatusBarState.KEYGUARD), eq(false) /* force */); // If useFullscreenUserSwitcher is true, state is set to FULLSCREEN_USER_SWITCHER. when(mUserSwitcherController.useFullscreenUserSwitcher()).thenReturn(true); mStatusBar.showKeyguardImpl(); - verify(mStatusBarStateController).setState(eq(StatusBarState.FULLSCREEN_USER_SWITCHER)); + verify(mStatusBarStateController).setState( + eq(StatusBarState.FULLSCREEN_USER_SWITCHER), eq(false) /* force */); } @Test 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 3cf92126c5c6..208790b24d8a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java @@ -429,8 +429,19 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { } @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 9b177e1cd0e5..5efe05f6db46 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 @@ public class ToastUITest extends SysuiTestCase { 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 @@ public class ToastUITest extends SysuiTestCase { } @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/overlays/AvoidAppsInCutoutOverlay/res/values-af/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-af/strings.xml index 8c47bcc9cb26..adc308600ebb 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 0f1edf682d0a..648e1d4cf383 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 71f4f7cab57a..2d3b506d8cad 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 e462ec68ddd9..db2b15a142c3 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 fc7e546d8ede..a6b7c4346e7e 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 c21fcda7e112..f80fa8d14054 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 8ef67a22cd45..0e5c8bcb55a2 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 8b81d6ad9fe7..e97bb57068ca 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 15b1fdc2b6fb..d13c777fe468 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 eb2b8d258bc6..9c9f43779b66 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 be3e093d42f9..e0a577e5290f 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 67ed6aff8661..0f64473c7260 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 dcf70bf22125..d0cc43e8025f 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 86e373263776..a7759ea6175a 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 9806966ffec7..b71679a1912f 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 a7700b9abd34..8c85cbdebb92 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 a7700b9abd34..8c85cbdebb92 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 a7700b9abd34..8c85cbdebb92 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 a7700b9abd34..8c85cbdebb92 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 e9b76fb8eb02..8b72d9f77c49 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 ee5f8eabb343..359cdd0eab52 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 c244e49f3160..47f525ec1d28 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 cf84a24a46db..0cc5a25868c2 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 f1a6fda82f97..15d7d6045361 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 f31fad1f83ab..0865f7559ef9 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 5e626eea210c..1a6bf7a16839 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 5c9194e8e694..ea0a27b069da 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 321ee66d7257..6d91a9d603f4 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 a05a5fdc08d1..382497b1caf0 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 557c7912166b..d578d9286d4c 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 c4ab1fe99bdc..e1f09f249bda 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 a2c1feb26c25..db734e8254e5 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 e8db0d1565de..264095b6f4e2 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 5b1838deb439..72e67ec1c424 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 d40d73b72454..c49bf0ca939a 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 1a2466532dfe..0b90991b0b1e 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 90b98100de50..2a0f026b39a6 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 0c4af2d69e4a..cc7a0a486c54 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 69b9f24d1d08..9e99482e5e2a 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 1ee2faef0bc6..5464a5699449 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 922152477d65..6a2623f8696f 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 ea0a9d0dbc5b..4b4d169cc738 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 10176a8d7b72..7a929d13d83f 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 97856d35618c..4b9e64020eee 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 039bdf0b8888..1ac6a8bb9c1f 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 29ec22453e93..4c38580169af 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 09d86412e408..c43736d006dd 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 f2367c648ed0..f95abb69abf5 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 67b45d3020a3..ff236be46b14 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 6e88f296e0ba..ef728ab64ab5 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 9bda419a1e17..23dbe0c822f0 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 ecd0c0b4f25e..42f09cb1a1f0 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 5864ff8689dd..e348630e0447 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 0f3c0aaff18d..90cb0a5f56a4 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 8a1da687e573..b8b4e7526ab2 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 98d75129f64a..bd213bb64a0d 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 0e515147c0ab..68f5c0701beb 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 b0552b87d5b3..162a29e8968c 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 803a69d40213..908393b1abb0 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 e8d7fb7dacc8..c027d5266928 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 b5364e996b91..d09ed97121fa 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 e9467a2879c4..d38ce43204d2 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 b5364e996b91..d09ed97121fa 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 9aefb31c69c6..6e5947c0d753 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 8335c77fc86d..c7f54bbff6a7 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 d21b02c04bdf..4a14a360e857 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 dfd01afb4c4b..98b82e636392 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 704dfbbfb99f..dcf0c842cd36 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 8035d7f26ffa..d7b0676970b8 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 c835b3582e25..c2b611e70da9 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 a8fd15730ba4..3007ffb99e10 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 57ef68437013..b605554b46f3 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 c0506cf7df5e..c4d06fb68564 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 db2a79787978..08fa4ae7669b 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 09d597dd456d..9a302507411a 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 6b1c3720ce8b..a3d4a3afe376 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 991a8406808e..12e0f3019814 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 7d6c068fd7e0..08b1521a12a0 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 48c5d14498b1..711b5389b26c 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 13a56acbab51..7f6f2b45fbd2 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 221786294eb5..a7d54fbae9f5 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 3d672b4c086f..f596520fad30 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 7f37f3bfb488..ddb1df77b00c 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 ff50ddbdff94..7aad79c11bf2 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 d6d772777d92..d861c5e60708 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/DisplayCutoutEmulationWaterfallOverlay/res/values/config.xml b/packages/overlays/DisplayCutoutEmulationWaterfallOverlay/res/values/config.xml index b9c5f1ded3d5..8d0227eed875 100644 --- a/packages/overlays/DisplayCutoutEmulationWaterfallOverlay/res/values/config.xml +++ b/packages/overlays/DisplayCutoutEmulationWaterfallOverlay/res/values/config.xml @@ -25,9 +25,9 @@ <!-- Max((28 + 20), 0) = 48 --> <dimen name="status_bar_height_landscape">48dp</dimen> <!-- Height of area above QQS where battery/time go (equal to status bar height if > 48dp) --> - <dimen name="quick_qs_offset_height">28dp</dimen> + <dimen name="quick_qs_offset_height">48dp</dimen> <!-- Total height of QQS (quick_qs_offset_height + 128) --> - <dimen name="quick_qs_total_height">156dp</dimen> + <dimen name="quick_qs_total_height">176dp</dimen> <dimen name="waterfall_display_left_edge_size">20dp</dimen> <dimen name="waterfall_display_top_edge_size">0dp</dimen> diff --git a/packages/services/CameraExtensionsProxy/src/com/android/camera/CameraExtensionsProxyService.java b/packages/services/CameraExtensionsProxy/src/com/android/camera/CameraExtensionsProxyService.java index d44a4173fc12..7b9ca2ddc345 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 @@ public class CameraExtensionsProxyService extends Service { 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 class CameraExtensionsProxyService extends Service { 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 class CameraExtensionsProxyService extends Service { 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 @@ public class CameraExtensionsProxyService extends Service { @Override public boolean advancedExtensionsSupported() { - return ADVANCED_VERSION_SUPPORTED; + return ADVANCED_API_SUPPORTED; } @Override @@ -819,10 +831,11 @@ public class CameraExtensionsProxyService extends Service { } @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 @@ public class CameraExtensionsProxyService extends Service { @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 @@ public class CameraExtensionsProxyService extends Service { @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 @@ public class CameraExtensionsProxyService extends Service { @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 @@ public class CameraExtensionsProxyService extends Service { @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 @@ public class CameraExtensionsProxyService extends Service { 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/accessibility/java/com/android/server/accessibility/MotionEventInjector.java b/services/accessibility/java/com/android/server/accessibility/MotionEventInjector.java index 3310cb4e3e79..ea2c7d2a41e9 100644 --- a/services/accessibility/java/com/android/server/accessibility/MotionEventInjector.java +++ b/services/accessibility/java/com/android/server/accessibility/MotionEventInjector.java @@ -31,9 +31,9 @@ import android.util.SparseArray; import android.util.SparseIntArray; import android.view.InputDevice; import android.view.MotionEvent; +import android.view.WindowManagerPolicyConstants; import com.android.internal.os.SomeArgs; -import com.android.server.policy.WindowManagerPolicy; import java.util.ArrayList; import java.util.Arrays; @@ -122,6 +122,12 @@ public class MotionEventInjector extends BaseEventStreamTransformation implement return; } cancelAnyPendingInjectedEvents(); + // The events injected from outside of system_server are not trusted. Remove the flag to + // prevent accessibility service from impersonating a real input device. + policyFlags &= ~WindowManagerPolicyConstants.FLAG_INPUTFILTER_TRUSTED; + // Indicate that the input event is injected from accessibility, to let applications + // distinguish it from events injected by other means. + policyFlags |= WindowManagerPolicyConstants.FLAG_INJECTED_FROM_ACCESSIBILITY; sendMotionEventToNext(event, rawEvent, policyFlags); } @@ -156,7 +162,9 @@ public class MotionEventInjector extends BaseEventStreamTransformation implement return false; } MotionEvent motionEvent = (MotionEvent) message.obj; - sendMotionEventToNext(motionEvent, motionEvent, WindowManagerPolicy.FLAG_PASS_TO_USER); + sendMotionEventToNext(motionEvent, motionEvent, + WindowManagerPolicyConstants.FLAG_PASS_TO_USER + | WindowManagerPolicyConstants.FLAG_INJECTED_FROM_ACCESSIBILITY); boolean isEndOfSequence = message.arg1 != 0; if (isEndOfSequence) { notifyService(mServiceInterfaceForCurrentGesture, mSequencesInProgress.get(0), true); @@ -308,7 +316,8 @@ public class MotionEventInjector extends BaseEventStreamTransformation implement MotionEvent cancelEvent = obtainMotionEvent(now, now, MotionEvent.ACTION_CANCEL, getLastTouchPoints(), 1); sendMotionEventToNext(cancelEvent, cancelEvent, - WindowManagerPolicy.FLAG_PASS_TO_USER); + WindowManagerPolicyConstants.FLAG_PASS_TO_USER + | WindowManagerPolicyConstants.FLAG_INJECTED_FROM_ACCESSIBILITY); mOpenGesturesInProgress.put(source, false); } } diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java index 4e14411dd06e..acbf4875ae8d 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 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku 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/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java index 83dfe8ed2576..05131d44b01e 100644 --- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java +++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java @@ -454,19 +454,13 @@ public class CompanionDeviceManagerService extends SystemService implements Bind }).cancelTimeout(); }, FgThread.getExecutor()).whenComplete(uncheckExceptions((association, err) -> { - - final long callingIdentity = Binder.clearCallingIdentity(); - try { - if (err == null) { - addAssociation(association); - } else { - Slog.e(LOG_TAG, "Failed to discover device(s)", err); - callback.onFailure("No devices found: " + err.getMessage()); - } - cleanup(); - } finally { - Binder.restoreCallingIdentity(callingIdentity); + if (err == null) { + addAssociation(association); + } else { + Slog.e(LOG_TAG, "Failed to discover device(s)", err); + callback.onFailure("No devices found: " + err.getMessage()); } + cleanup(); })); } diff --git a/services/core/java/com/android/server/MasterClearReceiver.java b/services/core/java/com/android/server/MasterClearReceiver.java index e248b215ef4a..b2f539680252 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 @@ public class MasterClearReceiver extends BroadcastReceiver { 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 @@ public class MasterClearReceiver extends BroadcastReceiver { } } + 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 84f40cb4b84f..a481a6a5d339 100644 --- a/services/core/java/com/android/server/NsdService.java +++ b/services/core/java/com/android/server/NsdService.java @@ -61,6 +61,7 @@ public class NsdService extends INsdManager.Stub { 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 @@ public class NsdService extends INsdManager.Stub { 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 @@ public class NsdService extends INsdManager.Stub { 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 @@ public class NsdService extends INsdManager.Stub { 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 @@ public class NsdService extends INsdManager.Stub { 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 @@ public class NsdService extends INsdManager.Stub { @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 @@ public class NsdService extends INsdManager.Stub { 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 @@ public class NsdService extends INsdManager.Stub { 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 @@ public class NsdService extends INsdManager.Stub { break; } + maybeStartDaemon(); id = getUniqueId(); if (discoverServices(id, servInfo.getServiceType())) { if (DBG) { @@ -316,6 +332,7 @@ public class NsdService extends INsdManager.Stub { break; } + maybeStartDaemon(); id = getUniqueId(); if (registerService(id, (NsdServiceInfo) msg.obj)) { if (DBG) Slog.d(TAG, "Register " + msg.arg2 + " " + id); @@ -357,6 +374,7 @@ public class NsdService extends INsdManager.Stub { break; } + maybeStartDaemon(); id = getUniqueId(); if (resolveService(id, servInfo)) { clientInfo.mResolvedService = new NsdServiceInfo(); @@ -513,6 +531,10 @@ public class NsdService extends INsdManager.Stub { } } + 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 @@ public class NsdService extends INsdManager.Stub { } @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 @@ public class NsdService extends INsdManager.Stub { 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 @@ public class NsdService extends INsdManager.Stub { @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 @@ public class NsdService extends INsdManager.Stub { 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 @@ public class NsdService extends INsdManager.Stub { } 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 7e2274b65f55..f9fd10817627 100644 --- a/services/core/java/com/android/server/VcnManagementService.java +++ b/services/core/java/com/android/server/VcnManagementService.java @@ -18,6 +18,7 @@ package com.android.server; 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.BroadcastReceiver; 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; 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 @@ public class VcnManagementService extends IVcnManagementService.Stub { @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 @@ public class VcnManagementService extends IVcnManagementService.Stub { @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 @@ public class VcnManagementService extends IVcnManagementService.Stub { 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 517a8294de9f..5e388d94869d 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -122,6 +122,7 @@ import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.Message; +import android.os.PowerExemptionManager; import android.os.PowerExemptionManager.ReasonCode; import android.os.Process; import android.os.RemoteCallback; @@ -1790,6 +1791,7 @@ public final class ActiveServices { if (!r.fgRequired) { final long delayMs = SystemClock.elapsedRealtime() - r.createRealTime; if (delayMs > mAm.mConstants.mFgsStartForegroundTimeoutMs) { + resetFgsRestrictionLocked(r); setFgsRestrictionLocked(r.serviceInfo.packageName, r.app.getPid(), r.appInfo.uid, r.intent.getIntent(), r, r.userId,false); final String temp = "startForegroundDelayMs:" + delayMs; @@ -1850,7 +1852,6 @@ public final class ActiveServices { notification.flags |= Notification.FLAG_FOREGROUND_SERVICE; r.foregroundNoti = notification; r.foregroundServiceType = foregroundServiceType; - boolean enterForeground = false; if (!r.isForeground) { final ServiceMap smap = getServiceMapLocked(r.userId); if (smap != null) { @@ -1876,8 +1877,12 @@ public final class ActiveServices { active.mNumActive++; } r.isForeground = true; - r.mLogEntering = true; - enterForeground = true; + // The logging of FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER event could + // be deferred, make a copy of mAllowStartForeground and + // mAllowWhileInUsePermissionInFgs. + r.mAllowStartForegroundAtEntering = r.mAllowStartForeground; + r.mAllowWhileInUsePermissionInFgsAtEntering = + r.mAllowWhileInUsePermissionInFgs; r.mStartForegroundCount++; r.mFgsEnterTime = SystemClock.uptimeMillis(); if (!stopProcStatsOp) { @@ -1897,6 +1902,9 @@ public final class ActiveServices { AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE); registerAppOpCallbackLocked(r); mAm.updateForegroundServiceUsageStats(r.name, r.userId, true); + logFGSStateChangeLocked(r, + FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER, + 0); } // Even if the service is already a FGS, we need to update the notification, // so we need to call it again. @@ -1952,6 +1960,7 @@ public final class ActiveServices { FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__EXIT, r.mFgsExitTime > r.mFgsEnterTime ? (int)(r.mFgsExitTime - r.mFgsEnterTime) : 0); + r.mFgsNotificationWasDeferred = false; resetFgsRestrictionLocked(r); mAm.updateForegroundServiceUsageStats(r.name, r.userId, false); if (r.app != null) { @@ -2156,6 +2165,7 @@ public final class ActiveServices { } r.fgDisplayTime = when; r.mFgsNotificationDeferred = true; + r.mFgsNotificationWasDeferred = true; r.mFgsNotificationShown = false; mPendingFgsNotifications.add(r); if (DEBUG_FOREGROUND_SERVICE) { @@ -2199,11 +2209,6 @@ public final class ActiveServices { Slog.d(TAG_SERVICE, " - service no longer running/fg, ignoring"); } } - // Regardless of whether we needed to post the notification or the - // service is no longer running, we may not have logged its FGS - // transition yet depending on the timing and API sequence that led - // to this point - so make sure to do so. - maybeLogFGSStateEnteredLocked(r); } } if (DEBUG_FOREGROUND_SERVICE) { @@ -2246,16 +2251,6 @@ public final class ActiveServices { } } - private void maybeLogFGSStateEnteredLocked(ServiceRecord r) { - if (r.mLogEntering) { - logFGSStateChangeLocked(r, - FrameworkStatsLog - .FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER, - 0); - r.mLogEntering = false; - } - } - /** * Callback from NotificationManagerService whenever it posts a notification * associated with a foreground service. This is the unified handling point @@ -2274,9 +2269,7 @@ public final class ActiveServices { && id == sr.foregroundId && sr.appInfo.packageName.equals(pkg)) { // Found it. If 'shown' is false, it means that the notification - // subsystem will not be displaying it yet, so all we do is log - // the "fgs entered" transition noting deferral, then we're done. - maybeLogFGSStateEnteredLocked(sr); + // subsystem will not be displaying it yet. if (shown) { if (DEBUG_FOREGROUND_SERVICE) { Slog.d(TAG_SERVICE, "Notification shown; canceling deferral of " @@ -4234,6 +4227,7 @@ public final class ActiveServices { r.isForeground = false; r.foregroundId = 0; r.foregroundNoti = null; + r.mFgsNotificationWasDeferred = false; resetFgsRestrictionLocked(r); // Clear start entries. @@ -4908,7 +4902,8 @@ public final class ActiveServices { 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)) { @@ -6234,19 +6229,29 @@ public final class ActiveServices { r.packageName, mAm.mConstants.mFgsAtomSampleRate)) { return; } + boolean allowWhileInUsePermissionInFgs; + @PowerExemptionManager.ReasonCode int fgsStartReasonCode; + if (state == FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER + || state == FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__EXIT) { + allowWhileInUsePermissionInFgs = r.mAllowWhileInUsePermissionInFgsAtEntering; + fgsStartReasonCode = r.mAllowStartForegroundAtEntering; + } else { + allowWhileInUsePermissionInFgs = r.mAllowWhileInUsePermissionInFgs; + fgsStartReasonCode = r.mAllowStartForeground; + } FrameworkStatsLog.write(FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED, r.appInfo.uid, r.shortInstanceName, state, - r.mAllowWhileInUsePermissionInFgs, - r.mAllowStartForeground, + allowWhileInUsePermissionInFgs, + fgsStartReasonCode, r.appInfo.targetSdkVersion, r.mRecentCallingUid, r.mRecentCallerApplicationInfo != null ? r.mRecentCallerApplicationInfo.targetSdkVersion : 0, r.mInfoTempFgsAllowListReason != null ? r.mInfoTempFgsAllowListReason.mCallingUid : INVALID_UID, - r.mFgsNotificationDeferred, + r.mFgsNotificationWasDeferred, r.mFgsNotificationShown, durationMs, r.mStartForegroundCount, diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index c841fa3b057c..2de091bb34bf 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -7124,54 +7124,61 @@ public class ActivityManagerService extends IActivityManager.Stub 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; - } - } + 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 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; - } + // 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; - } - } + 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; } @@ -14309,7 +14316,7 @@ public class ActivityManagerService extends IActivityManager.Stub 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); @@ -15349,6 +15356,11 @@ public class ActivityManagerService extends IActivityManager.Stub } @Override + public int[] getStartedUserIds() { + return mUserController.getStartedUserArray(); + } + + @Override public void setPendingIntentAllowBgActivityStarts(IIntentSender target, IBinder allowlistToken, int flags) { if (!(target instanceof PendingIntentRecord)) { diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java index 0757e7b6bd7d..d71919e1274c 100644 --- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java +++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java @@ -102,7 +102,6 @@ import com.android.server.am.LowMemDetector.MemFactor; import com.android.server.compat.PlatformCompat; import java.io.BufferedReader; -import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -806,8 +805,7 @@ final class ActivityManagerShellCommand extends ShellCommand { return -1; } - File file = new File(filename); - file.delete(); + // Writes an error message to stderr on failure ParcelFileDescriptor fd = openFileForSystem(filename, "w"); if (fd == null) { return -1; @@ -961,16 +959,16 @@ final class ActivityManagerShellCommand extends ShellCommand { String logNameTimeString = LOG_NAME_TIME_FORMATTER.format(localDateTime); heapFile = "/data/local/tmp/heapdump-" + logNameTimeString + ".prof"; } - pw.println("File: " + heapFile); - pw.flush(); - File file = new File(heapFile); - file.delete(); + // Writes an error message to stderr on failure ParcelFileDescriptor fd = openFileForSystem(heapFile, "w"); if (fd == null) { return -1; } + pw.println("File: " + heapFile); + pw.flush(); + final CountDownLatch latch = new CountDownLatch(1); final RemoteCallback finishCallback = new RemoteCallback(new OnResultListener() { diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java index 3bfd62b60c89..8ebc987a59f4 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 @@ public final class ProcessList { 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 @@ public final class ProcessList { 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/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java index dd1ddd73a84f..141f081ab9a7 100644 --- a/services/core/java/com/android/server/am/ServiceRecord.java +++ b/services/core/java/com/android/server/am/ServiceRecord.java @@ -18,7 +18,7 @@ package com.android.server.am; import static android.app.PendingIntent.FLAG_IMMUTABLE; import static android.app.PendingIntent.FLAG_UPDATE_CURRENT; -import static android.os.PowerWhitelistManager.REASON_DENIED; +import static android.os.PowerExemptionManager.REASON_DENIED; import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; @@ -37,7 +37,7 @@ import android.net.Uri; import android.os.Binder; import android.os.Build; import android.os.IBinder; -import android.os.PowerWhitelistManager; +import android.os.PowerExemptionManager; import android.os.SystemClock; import android.os.UserHandle; import android.provider.Settings; @@ -109,7 +109,6 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN boolean fgWaiting; // is a timeout for going foreground already scheduled? boolean isNotAppComponentUsage; // is service binding not considered component/package usage? boolean isForeground; // is service currently in foreground mode? - boolean mLogEntering; // need to report fgs transition once deferral policy is known int foregroundId; // Notification ID of last foreground req. Notification foregroundNoti; // Notification record of foreground state. long fgDisplayTime; // time at which the FGS notification should become visible @@ -153,6 +152,8 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN // allow while-in-use permissions in foreground service or not. // while-in-use permissions in FGS started from background might be restricted. boolean mAllowWhileInUsePermissionInFgs; + // A copy of mAllowWhileInUsePermissionInFgs's value when the service is entering FGS state. + boolean mAllowWhileInUsePermissionInFgsAtEntering; // the most recent package that start/bind this service. String mRecentCallingPackage; @@ -165,14 +166,18 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN long mFgsEnterTime = 0; // The uptime when the service exits FGS state. long mFgsExitTime = 0; - // FGS notification was deferred. + // FGS notification is deferred. boolean mFgsNotificationDeferred; + // FGS notification was deferred. + boolean mFgsNotificationWasDeferred; // FGS notification was shown before the FGS finishes, or it wasn't deferred in the first place. boolean mFgsNotificationShown; // allow the service becomes foreground service? Service started from background may not be // allowed to become a foreground service. - @PowerWhitelistManager.ReasonCode int mAllowStartForeground = REASON_DENIED; + @PowerExemptionManager.ReasonCode int mAllowStartForeground = REASON_DENIED; + // A copy of mAllowStartForeground's value when the service is entering FGS state. + @PowerExemptionManager.ReasonCode int mAllowStartForegroundAtEntering = REASON_DENIED; // Debug info why mAllowStartForeground is allowed or denied. String mInfoAllowStartForeground; // Debug info if mAllowStartForeground is allowed because of a temp-allowlist. diff --git a/services/core/java/com/android/server/app/GameManagerService.java b/services/core/java/com/android/server/app/GameManagerService.java index 75367d27a8a1..697f6fa8eea8 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 @@ public final class GameManagerService extends IGameManagerService.Stub { } } - 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 @@ public final class GameManagerService extends IGameManagerService.Stub { // 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); } diff --git a/services/core/java/com/android/server/app/GameManagerShellCommand.java b/services/core/java/com/android/server/app/GameManagerShellCommand.java index c5f1a0b3f67e..2074ffae1030 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 @@ public class GameManagerShellCommand extends ShellCommand { * <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 @@ public class GameManagerShellCommand extends ShellCommand { 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 @@ public class GameManagerShellCommand extends ShellCommand { 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 535fb679ab4d..4cb2e9b5cb97 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 @@ public final class AppHibernationService extends SystemService { 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 c2259eb98e58..99a33e4462e2 100644 --- a/services/core/java/com/android/server/appop/AppOpsService.java +++ b/services/core/java/com/android/server/appop/AppOpsService.java @@ -667,12 +667,30 @@ public class AppOpsService extends IAppOpsService.Stub { /** 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) */ @@ -830,7 +848,7 @@ public class AppOpsService extends IAppOpsService.Stub { return mAttributionFlags; } - /** @return attributoin chiang id for the access */ + /** @return attribution chain id for the access */ public int getAttributionChainId() { return mAttributionChainId; } @@ -894,7 +912,8 @@ public class AppOpsService extends IAppOpsService.Stub { proxyAttributionTag, uidState, flags); mHistoricalRegistry.incrementOpAccessedCount(parent.op, parent.uid, parent.packageName, - tag, uidState, flags, accessTime); + tag, uidState, flags, accessTime, AppOpsManager.ATTRIBUTION_FLAGS_NONE, + AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE); } /** @@ -1011,7 +1030,7 @@ public class AppOpsService extends IAppOpsService.Stub { if (isStarted && mInProgressEvents == null) { mInProgressEvents = new ArrayMap<>(1); - } else if (mPausedInProgressEvents == null) { + } else if (!isStarted && mPausedInProgressEvents == null) { mPausedInProgressEvents = new ArrayMap<>(1); } ArrayMap<IBinder, InProgressStartOpEvent> events = isStarted @@ -1035,9 +1054,9 @@ public class AppOpsService extends IAppOpsService.Stub { event.numUnfinishedStarts++; if (isStarted) { - // TODO: Consider storing the attribution chain flags and id mHistoricalRegistry.incrementOpAccessedCount(parent.op, parent.uid, - parent.packageName, tag, uidState, flags, startTime); + parent.packageName, tag, uidState, flags, startTime, attributionFlags, + attributionChainId); } } @@ -1094,7 +1113,8 @@ public class AppOpsService extends IAppOpsService.Stub { mHistoricalRegistry.increaseOpAccessDuration(parent.op, parent.uid, parent.packageName, tag, event.getUidState(), - event.getFlags(), finishedEvent.getNoteTime(), finishedEvent.getDuration()); + event.getFlags(), finishedEvent.getNoteTime(), finishedEvent.getDuration(), + event.getAttributionFlags(), event.getAttributionChainId()); if (!isPausing) { mInProgressStartOpEventPool.release(event); @@ -1197,7 +1217,8 @@ public class AppOpsService extends IAppOpsService.Stub { event.mStartElapsedTime = SystemClock.elapsedRealtime(); event.mStartTime = startTime; mHistoricalRegistry.incrementOpAccessedCount(parent.op, parent.uid, - parent.packageName, tag, event.mUidState, event.mFlags, startTime); + parent.packageName, tag, event.mUidState, event.mFlags, startTime, + event.getAttributionFlags(), event.getAttributionChainId()); if (shouldSendActive) { scheduleOpActiveChangedIfNeededLocked(parent.op, parent.uid, parent.packageName, tag, true, event.getAttributionFlags(), event.getAttributionChainId()); @@ -1213,11 +1234,13 @@ public class AppOpsService extends IAppOpsService.Stub { */ void onClientDeath(@NonNull IBinder clientId) { synchronized (AppOpsService.this) { - if (mInProgressEvents == null) { + if (mInProgressEvents == null && mPausedInProgressEvents == null) { return; } - InProgressStartOpEvent deadEvent = mInProgressEvents.get(clientId); + ArrayMap<IBinder, InProgressStartOpEvent> events = isPaused() + ? mPausedInProgressEvents : mInProgressEvents; + InProgressStartOpEvent deadEvent = events.get(clientId); if (deadEvent != null) { deadEvent.numUnfinishedStarts = 1; } @@ -1232,14 +1255,18 @@ public class AppOpsService extends IAppOpsService.Stub { * @param newState The new state */ public void onUidStateChanged(@AppOpsManager.UidState int newState) { - if (mInProgressEvents == null) { + if (mInProgressEvents == null && mPausedInProgressEvents == null) { return; } - int numInProgressEvents = mInProgressEvents.size(); - List<IBinder> binders = new ArrayList<>(mInProgressEvents.keySet()); + boolean isRunning = isRunning(); + ArrayMap<IBinder, AppOpsService.InProgressStartOpEvent> events = + isRunning ? mInProgressEvents : mPausedInProgressEvents; + + int numInProgressEvents = events.size(); + List<IBinder> binders = new ArrayList<>(events.keySet()); for (int i = 0; i < numInProgressEvents; i++) { - InProgressStartOpEvent event = mInProgressEvents.get(binders.get(i)); + InProgressStartOpEvent event = events.get(binders.get(i)); if (event != null && event.getUidState() != newState) { try { @@ -1254,16 +1281,17 @@ public class AppOpsService extends IAppOpsService.Stub { // Call started() to add a new start event object and then add the // previously removed unfinished start counts back if (proxy != null) { - started(event.getClientId(), proxy.getUid(), proxy.getPackageName(), - proxy.getAttributionTag(), newState, event.getFlags(), false, + startedOrPaused(event.getClientId(), proxy.getUid(), + proxy.getPackageName(), proxy.getAttributionTag(), newState, + event.getFlags(), false, isRunning, event.getAttributionFlags(), event.getAttributionChainId()); } else { - started(event.getClientId(), Process.INVALID_UID, null, null, newState, - OP_FLAG_SELF, false, event.getAttributionFlags(), - event.getAttributionChainId()); + startedOrPaused(event.getClientId(), Process.INVALID_UID, null, null, + newState, event.getFlags(), false, isRunning, + event.getAttributionFlags(), event.getAttributionChainId()); } - InProgressStartOpEvent newEvent = mInProgressEvents.get(binders.get(i)); + InProgressStartOpEvent newEvent = events.get(binders.get(i)); if (newEvent != null) { newEvent.numUnfinishedStarts += numPreviousUnfinishedStarts - 1; } @@ -2225,7 +2253,8 @@ public class AppOpsService extends IAppOpsService.Stub { 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 +2416,7 @@ public class AppOpsService extends IAppOpsService.Stub { 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 +2726,9 @@ public class AppOpsService extends IAppOpsService.Stub { 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 +2737,7 @@ public class AppOpsService extends IAppOpsService.Stub { 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 +3177,9 @@ public class AppOpsService extends IAppOpsService.Stub { */ 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 +3189,7 @@ public class AppOpsService extends IAppOpsService.Stub { 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 +3199,7 @@ public class AppOpsService extends IAppOpsService.Stub { 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); } @@ -3341,16 +3370,16 @@ public class AppOpsService extends IAppOpsService.Stub { @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 @@ -3365,8 +3394,8 @@ public class AppOpsService extends IAppOpsService.Stub { } 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); @@ -3386,7 +3415,7 @@ public class AppOpsService extends IAppOpsService.Stub { 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); @@ -3862,15 +3891,15 @@ public class AppOpsService extends IAppOpsService.Stub { 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 @@ -3886,7 +3915,8 @@ public class AppOpsService extends IAppOpsService.Stub { 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, @@ -3901,7 +3931,7 @@ public class AppOpsService extends IAppOpsService.Stub { 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. @@ -4033,10 +4063,10 @@ public class AppOpsService extends IAppOpsService.Stub { 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) { @@ -4045,7 +4075,8 @@ public class AppOpsService extends IAppOpsService.Stub { } 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)); @@ -4427,32 +4458,35 @@ public class AppOpsService extends IAppOpsService.Stub { } /** - * @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) { @@ -4460,14 +4494,13 @@ public class AppOpsService extends IAppOpsService.Stub { 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); @@ -4479,12 +4512,16 @@ public class AppOpsService extends IAppOpsService.Stub { throw new SecurityException("Specified package " + packageName + " under uid " + 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) { @@ -4509,30 +4546,30 @@ public class AppOpsService extends IAppOpsService.Stub { 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; } try { - if (mPlatformCompat.isChangeEnabledByPackageName( + if (!mPlatformCompat.isChangeEnabledByPackageName( SECURITY_EXCEPTION_ON_INVALID_ATTRIBUTION_TAG_CHANGE, packageName, - userId) && mPlatformCompat.isChangeEnabledByUid( + userId) || !mPlatformCompat.isChangeEnabledByUid( SECURITY_EXCEPTION_ON_INVALID_ATTRIBUTION_TAG_CHANGE, - callingUid) && !foundInProxy) { - Slog.e(TAG, msg); - } else { - Slog.e(TAG, msg); + callingUid)) { + // Do not override tags if overriding is not enabled for this package + isAttributionTagValid = true; } + Slog.e(TAG, msg); } catch (RemoteException neverHappens) { } } @@ -4546,7 +4583,7 @@ public class AppOpsService extends IAppOpsService.Stub { + otherUidMessage); } - return bypass; + return new PackageVerificationResult(bypass, isAttributionTagValid); } private boolean isAttributionInPackage(@Nullable AndroidPackage pkg, @@ -4574,13 +4611,14 @@ public class AppOpsService extends IAppOpsService.Stub { * @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; @@ -4609,6 +4647,11 @@ public class AppOpsService extends IAppOpsService.Stub { if (attributionTag != null) { ops.knownAttributionTags.add(attributionTag); + if (isAttributionTagValid) { + ops.validAttributionTags.add(attributionTag); + } else { + ops.validAttributionTags.remove(attributionTag); + } } } @@ -4638,14 +4681,17 @@ public class AppOpsService extends IAppOpsService.Stub { * @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; } @@ -6458,9 +6504,9 @@ public class AppOpsService extends IAppOpsService.Stub { int numAttrTags = op.mAttributions.size(); for (int attrNum = 0; attrNum < numAttrTags; attrNum++) { AttributedOp attrOp = op.mAttributions.valueAt(attrNum); - if (restricted) { + if (restricted && attrOp.isRunning()) { attrOp.pause(); - } else { + } else if (attrOp.isPaused()) { attrOp.resume(); } } @@ -6510,7 +6556,7 @@ public class AppOpsService extends IAppOpsService.Stub { } // 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/appop/DiscreteRegistry.java b/services/core/java/com/android/server/appop/DiscreteRegistry.java index 10cfddfb3ae4..49469cc8a597 100644 --- a/services/core/java/com/android/server/appop/DiscreteRegistry.java +++ b/services/core/java/com/android/server/appop/DiscreteRegistry.java @@ -26,6 +26,7 @@ import static android.app.AppOpsManager.OP_FINE_LOCATION; import static android.app.AppOpsManager.OP_FLAGS_ALL; import static android.app.AppOpsManager.OP_FLAG_SELF; import static android.app.AppOpsManager.OP_FLAG_TRUSTED_PROXIED; +import static android.app.AppOpsManager.OP_FLAG_TRUSTED_PROXY; import static android.app.AppOpsManager.OP_NONE; import static android.app.AppOpsManager.OP_PHONE_CALL_CAMERA; import static android.app.AppOpsManager.OP_PHONE_CALL_MICROPHONE; @@ -156,8 +157,11 @@ final class DiscreteRegistry { private static final String ATTR_NOTE_DURATION = "nd"; private static final String ATTR_UID_STATE = "us"; private static final String ATTR_FLAGS = "f"; + private static final String ATTR_ATTRIBUTION_FLAGS = "af"; + private static final String ATTR_CHAIN_ID = "ci"; - private static final int OP_FLAGS_DISCRETE = OP_FLAG_SELF | OP_FLAG_TRUSTED_PROXIED; + private static final int OP_FLAGS_DISCRETE = OP_FLAG_SELF | OP_FLAG_TRUSTED_PROXIED + | OP_FLAG_TRUSTED_PROXY; // Lock for read/write access to on disk state private final Object mOnDiskLock = new Object(); @@ -227,13 +231,14 @@ final class DiscreteRegistry { void recordDiscreteAccess(int uid, String packageName, int op, @Nullable String attributionTag, @AppOpsManager.OpFlags int flags, @AppOpsManager.UidState int uidState, long accessTime, - long accessDuration) { + long accessDuration, @AppOpsManager.AttributionFlags int attributionFlags, + int attributionChainId) { if (!isDiscreteOp(op, flags)) { return; } synchronized (mInMemoryLock) { mDiscreteOps.addDiscreteAccess(op, uid, packageName, attributionTag, flags, uidState, - accessTime, accessDuration); + accessTime, accessDuration, attributionFlags, attributionChainId); } } @@ -383,9 +388,10 @@ final class DiscreteRegistry { void addDiscreteAccess(int op, int uid, @NonNull String packageName, @Nullable String attributionTag, @AppOpsManager.OpFlags int flags, - @AppOpsManager.UidState int uidState, long accessTime, long accessDuration) { + @AppOpsManager.UidState int uidState, long accessTime, long accessDuration, + @AppOpsManager.AttributionFlags int attributionFlags, int attributionChainId) { getOrCreateDiscreteUidOps(uid).addDiscreteAccess(op, packageName, attributionTag, flags, - uidState, accessTime, accessDuration); + uidState, accessTime, accessDuration, attributionFlags, attributionChainId); } private void filter(long beginTimeMillis, long endTimeMillis, @@ -613,9 +619,10 @@ final class DiscreteRegistry { void addDiscreteAccess(int op, @NonNull String packageName, @Nullable String attributionTag, @AppOpsManager.OpFlags int flags, @AppOpsManager.UidState int uidState, - long accessTime, long accessDuration) { + long accessTime, long accessDuration, + @AppOpsManager.AttributionFlags int attributionFlags, int attributionChainId) { getOrCreateDiscretePackageOps(packageName).addDiscreteAccess(op, attributionTag, flags, - uidState, accessTime, accessDuration); + uidState, accessTime, accessDuration, attributionFlags, attributionChainId); } private DiscretePackageOps getOrCreateDiscretePackageOps(String packageName) { @@ -680,9 +687,10 @@ final class DiscreteRegistry { void addDiscreteAccess(int op, @Nullable String attributionTag, @AppOpsManager.OpFlags int flags, @AppOpsManager.UidState int uidState, - long accessTime, long accessDuration) { + long accessTime, long accessDuration, + @AppOpsManager.AttributionFlags int attributionFlags, int attributionChainId) { getOrCreateDiscreteOp(op).addDiscreteAccess(attributionTag, flags, uidState, accessTime, - accessDuration); + accessDuration, attributionFlags, attributionChainId); } void merge(DiscretePackageOps other) { @@ -823,37 +831,39 @@ final class DiscreteRegistry { for (int j = 0; j < n; j++) { DiscreteOpEvent event = list.get(j); list.set(j, new DiscreteOpEvent(event.mNoteTime - offset, event.mNoteDuration, - event.mUidState, event.mOpFlag)); + event.mUidState, event.mOpFlag, event.mAttributionFlags, + event.mAttributionChainId)); } } } void addDiscreteAccess(@Nullable String attributionTag, @AppOpsManager.OpFlags int flags, @AppOpsManager.UidState int uidState, - long accessTime, long accessDuration) { + long accessTime, long accessDuration, + @AppOpsManager.AttributionFlags int attributionFlags, int attributionChainId) { List<DiscreteOpEvent> attributedOps = getOrCreateDiscreteOpEventsList( attributionTag); - accessTime = accessTime / sDiscreteHistoryQuantization * sDiscreteHistoryQuantization; - accessDuration = accessDuration == -1 ? -1 - : (accessDuration + sDiscreteHistoryQuantization - 1) - / sDiscreteHistoryQuantization * sDiscreteHistoryQuantization; int nAttributedOps = attributedOps.size(); int i = nAttributedOps; for (; i > 0; i--) { DiscreteOpEvent previousOp = attributedOps.get(i - 1); - if (previousOp.mNoteTime < accessTime) { + if (discretizeTimeStamp(previousOp.mNoteTime) < discretizeTimeStamp(accessTime)) { break; } - if (previousOp.mOpFlag == flags && previousOp.mUidState == uidState) { - if (accessDuration != previousOp.mNoteDuration) { + if (previousOp.mOpFlag == flags && previousOp.mUidState == uidState + && previousOp.mAttributionFlags == attributionFlags + && previousOp.mAttributionChainId == attributionChainId) { + if (discretizeDuration(accessDuration) != discretizeDuration( + previousOp.mNoteDuration)) { break; } else { return; } } } - attributedOps.add(i, new DiscreteOpEvent(accessTime, accessDuration, uidState, flags)); + attributedOps.add(i, new DiscreteOpEvent(accessTime, accessDuration, uidState, flags, + attributionFlags, attributionChainId)); } private List<DiscreteOpEvent> getOrCreateDiscreteOpEventsList(String attributionTag) { @@ -875,7 +885,8 @@ final class DiscreteRegistry { for (int j = 0; j < nEvents; j++) { DiscreteOpEvent event = events.get(j); result.addDiscreteAccess(op, uid, packageName, tag, event.mUidState, - event.mOpFlag, event.mNoteTime, event.mNoteDuration); + event.mOpFlag, discretizeTimeStamp(event.mNoteTime), + discretizeDuration(event.mNoteDuration)); } } } @@ -932,11 +943,15 @@ final class DiscreteRegistry { -1); int uidState = parser.getAttributeInt(null, ATTR_UID_STATE); int opFlags = parser.getAttributeInt(null, ATTR_FLAGS); + int attributionFlags = parser.getAttributeInt(null, + ATTR_ATTRIBUTION_FLAGS, AppOpsManager.ATTRIBUTION_FLAGS_NONE); + int attributionChainId = parser.getAttributeInt(null, ATTR_CHAIN_ID, + AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE); if (noteTime + noteDuration < beginTimeMillis) { continue; } DiscreteOpEvent event = new DiscreteOpEvent(noteTime, noteDuration, - uidState, opFlags); + uidState, opFlags, attributionFlags, attributionChainId); events.add(event); } } @@ -952,13 +967,18 @@ final class DiscreteRegistry { final long mNoteDuration; final @AppOpsManager.UidState int mUidState; final @AppOpsManager.OpFlags int mOpFlag; + final @AppOpsManager.AttributionFlags int mAttributionFlags; + final int mAttributionChainId; DiscreteOpEvent(long noteTime, long noteDuration, @AppOpsManager.UidState int uidState, - @AppOpsManager.OpFlags int opFlag) { + @AppOpsManager.OpFlags int opFlag, + @AppOpsManager.AttributionFlags int attributionFlags, int attributionChainId) { mNoteTime = noteTime; mNoteDuration = noteDuration; mUidState = uidState; mOpFlag = opFlag; + mAttributionFlags = attributionFlags; + mAttributionChainId = attributionChainId; } private void dump(@NonNull PrintWriter pw, @NonNull SimpleDateFormat sdf, @@ -969,13 +989,19 @@ final class DiscreteRegistry { pw.print("-"); pw.print(flagsToString(mOpFlag)); pw.print("] at "); - date.setTime(mNoteTime); + date.setTime(discretizeTimeStamp(mNoteTime)); pw.print(sdf.format(date)); if (mNoteDuration != -1) { pw.print(" for "); - pw.print(mNoteDuration); + pw.print(discretizeDuration(mNoteDuration)); pw.print(" milliseconds "); } + if (mAttributionFlags != AppOpsManager.ATTRIBUTION_FLAGS_NONE) { + pw.print(" attribution flags="); + pw.print(mAttributionFlags); + pw.print(" with chainId="); + pw.print(mAttributionChainId); + } pw.println(); } @@ -984,6 +1010,12 @@ final class DiscreteRegistry { if (mNoteDuration != -1) { out.attributeLong(null, ATTR_NOTE_DURATION, mNoteDuration); } + if (mAttributionFlags != AppOpsManager.ATTRIBUTION_FLAGS_NONE) { + out.attributeInt(null, ATTR_ATTRIBUTION_FLAGS, mAttributionFlags); + } + if (mAttributionChainId != AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE) { + out.attributeInt(null, ATTR_CHAIN_ID, mAttributionChainId); + } out.attributeInt(null, ATTR_UID_STATE, mUidState); out.attributeInt(null, ATTR_FLAGS, mOpFlag); } @@ -1055,6 +1087,16 @@ final class DiscreteRegistry { return true; } + private static long discretizeTimeStamp(long timeStamp) { + return timeStamp / sDiscreteHistoryQuantization * sDiscreteHistoryQuantization; + + } + + private static long discretizeDuration(long duration) { + return duration == -1 ? -1 : (duration + sDiscreteHistoryQuantization - 1) + / sDiscreteHistoryQuantization * sDiscreteHistoryQuantization; + } + void setDebugMode(boolean debugMode) { this.mDebugMode = debugMode; } diff --git a/services/core/java/com/android/server/appop/HistoricalRegistry.java b/services/core/java/com/android/server/appop/HistoricalRegistry.java index 8b72be78a7f6..dd5df503d936 100644 --- a/services/core/java/com/android/server/appop/HistoricalRegistry.java +++ b/services/core/java/com/android/server/appop/HistoricalRegistry.java @@ -487,7 +487,8 @@ final class HistoricalRegistry { void incrementOpAccessedCount(int op, int uid, @NonNull String packageName, @Nullable String attributionTag, @UidState int uidState, @OpFlags int flags, - long accessTime) { + long accessTime, @AppOpsManager.AttributionFlags int attributionFlags, + int attributionChainId) { synchronized (mInMemoryLock) { if (mMode == AppOpsManager.HISTORICAL_MODE_ENABLED_ACTIVE) { if (!isPersistenceInitializedMLocked()) { @@ -499,7 +500,7 @@ final class HistoricalRegistry { attributionTag, uidState, flags, 1); mDiscreteRegistry.recordDiscreteAccess(uid, packageName, op, attributionTag, - flags, uidState, accessTime, -1); + flags, uidState, accessTime, -1, attributionFlags, attributionChainId); } } } @@ -521,7 +522,8 @@ final class HistoricalRegistry { void increaseOpAccessDuration(int op, int uid, @NonNull String packageName, @Nullable String attributionTag, @UidState int uidState, @OpFlags int flags, - long eventStartTime, long increment) { + long eventStartTime, long increment, + @AppOpsManager.AttributionFlags int attributionFlags, int attributionChainId) { synchronized (mInMemoryLock) { if (mMode == AppOpsManager.HISTORICAL_MODE_ENABLED_ACTIVE) { if (!isPersistenceInitializedMLocked()) { @@ -532,7 +534,8 @@ final class HistoricalRegistry { System.currentTimeMillis()).increaseAccessDuration(op, uid, packageName, attributionTag, uidState, flags, increment); mDiscreteRegistry.recordDiscreteAccess(uid, packageName, op, attributionTag, - flags, uidState, eventStartTime, increment); + flags, uidState, eventStartTime, increment, attributionFlags, + attributionChainId); } } } diff --git a/services/core/java/com/android/server/biometrics/AuthService.java b/services/core/java/com/android/server/biometrics/AuthService.java index 6f73985fbcd4..5cd330a5753c 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.Manifest.permission.USE_FINGERPRINT; 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 @@ import java.util.List; */ 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 class AuthService extends SystemService { 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 @@ public class AuthService extends SystemService { } if (!checkAppOps(callingUid, opPackageName, "authenticate()")) { - Slog.e(TAG, "Denied by app ops: " + opPackageName); + authenticateFastFail("Denied by app ops: " + opPackageName, receiver); return; } - if (!Utils.isForeground(callingUid, callingPid)) { - Slog.e(TAG, "Caller is not foreground: " + opPackageName); + if (token == null || receiver == null || opPackageName == null || promptInfo == null) { + authenticateFastFail( + "Unable to authenticate, one or more null arguments", receiver); return; } - if (token == null || receiver == null || opPackageName == null || promptInfo == null) { - Slog.e(TAG, "Unable to authenticate, one or more null arguments"); + if (!Utils.isForeground(callingUid, callingPid)) { + authenticateFastFail("Caller is not foreground: " + opPackageName, receiver); return; } @@ -257,6 +258,17 @@ public class AuthService extends SystemService { } } + 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 ef02a472969b..8f364890aa06 100644 --- a/services/core/java/com/android/server/biometrics/AuthSession.java +++ b/services/core/java/com/android/server/biometrics/AuthSession.java @@ -679,7 +679,8 @@ public final class AuthSession implements IBinder.DeathRecipient { FrameworkStatsLog.BIOMETRIC_AUTHENTICATED__STATE__CONFIRMED, latency, mDebugEnabled, - -1 /* sensorId */); + -1 /* sensorId */, + -1f /* ambientLightLux */); } else { final long latency = System.currentTimeMillis() - mStartTimeMs; 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 99f4e2cb280c..f51b1c2a4f0c 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 @@ public abstract class BaseClientMonitor extends LoggableMonitor } } + /** 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 @@ public abstract class BaseClientMonitor extends LoggableMonitor @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 @@ public abstract class BaseClientMonitor extends LoggableMonitor * @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 4da644d23dec..c8867ea2df1c 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,26 +43,47 @@ public abstract class LoggableMonitor { 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; - /** - * Only valid for AuthenticationClient. - * @return true if the client is authenticating for a crypto operation. - */ - protected boolean isCryptoOperation() { - return false; - } + // 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(int statsModality, int statsAction, int statsClient) { + 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. + */ + protected boolean isCryptoOperation() { + return false; } protected void setShouldLog(boolean shouldLog) { @@ -131,7 +158,6 @@ public abstract class LoggableMonitor { } protected final void logOnError(Context context, int error, int vendorCode, int targetUserId) { - if (!mShouldLogMetrics) { return; } @@ -199,7 +225,8 @@ public abstract class LoggableMonitor { + ", Client: " + mStatsClient + ", RequireConfirmation: " + requireConfirmation + ", State: " + authState - + ", Latency: " + latency); + + ", Latency: " + latency + + ", Lux: " + mLastAmbientLux); } else { Slog.v(TAG, "Authentication latency: " + latency); } @@ -217,7 +244,8 @@ public abstract class LoggableMonitor { 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 @@ public abstract class LoggableMonitor { + ", User: " + targetUserId + ", Client: " + mStatsClient + ", Latency: " + latency + + ", Lux: " + mLastAmbientLux + ", Success: " + enrollSuccessful); } else { Slog.v(TAG, "Enroll latency: " + latency); @@ -244,7 +273,8 @@ public abstract class LoggableMonitor { targetUserId, sanitizeLatency(latency), enrollSuccessful, - -1 /* sensorId */); + -1, /* sensorId */ + mLastAmbientLux /* ambientLightLux */); } private long sanitizeLatency(long latency) { @@ -255,4 +285,46 @@ public abstract class LoggableMonitor { 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 2ab1285ba8a7..2adf5f98cee5 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 @@ class FaceAuthenticationClient extends AuthenticationClient<ISession> implements "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 @@ class FaceAuthenticationClient extends AuthenticationClient<ISession> implements } } - @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 @@ class FaceAuthenticationClient extends AuthenticationClient<ISession> implements } } - @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 f97414780247..ff68aa87dbbb 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 @@ public class FaceEnrollClient extends EnrollClient<ISession> { 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 c4bdb320ddef..01dd18fb5cf0 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 @@ class FaceAuthenticationClient extends AuthenticationClient<IBiometricsFace> { "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 @@ class FaceAuthenticationClient extends AuthenticationClient<IBiometricsFace> { @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 fc1200a4b42a..d3bd18b6f704 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 @@ public class FaceEnrollClient extends EnrollClient<IBiometricsFace> { .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 a5326b352264..3c9d802cb4b1 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 @@ class FingerprintAuthenticationClient extends AuthenticationClient<ISession> imp 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 edd30bc6b333..11849661693b 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 @@ -79,6 +79,12 @@ class FingerprintEnrollClient extends EnrollClient<ISession> implements Udfps { } } + @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); 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 24ed85c42e4e..45e35e34b62b 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 @@ class FingerprintAuthenticationClient extends AuthenticationClient<IBiometricsFi 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 4f3e930c4e88..a28a3f6bd5c3 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 @@ public class FingerprintEnrollClient extends EnrollClient<IBiometricsFingerprint } } + @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 909ed11e9d69..6dca00191b24 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 @@ final class CompatConfig { * @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 @@ final class CompatConfig { /** * 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 @@ final class CompatConfig { * @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 @@ final class CompatConfig { */ 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 2cd68b086453..19e858c25c41 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 @@ public class PlatformCompat extends IPlatformCompat.Stub { @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); } } diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java index d4920f56a27e..fe5ee78bca31 100644 --- a/services/core/java/com/android/server/display/DisplayManagerService.java +++ b/services/core/java/com/android/server/display/DisplayManagerService.java @@ -512,6 +512,8 @@ public final class DisplayManagerService extends SystemService { } } } + } else if (phase == PHASE_BOOT_COMPLETED) { + mDisplayModeDirector.onBootCompleted(); } } @@ -3250,6 +3252,11 @@ public final class DisplayManagerService extends SystemService { mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY) .ignoreProximitySensorUntilChanged(); } + + @Override + public int getRefreshRateSwitchingType() { + return getRefreshRateSwitchingTypeInternal(); + } } class DesiredDisplayModeSpecsObserver diff --git a/services/core/java/com/android/server/display/DisplayModeDirector.java b/services/core/java/com/android/server/display/DisplayModeDirector.java index 997f0e5aa70c..07d13c251f26 100644 --- a/services/core/java/com/android/server/display/DisplayModeDirector.java +++ b/services/core/java/com/android/server/display/DisplayModeDirector.java @@ -155,7 +155,6 @@ public class DisplayModeDirector { mSettingsObserver.observe(); mDisplayObserver.observe(); mBrightnessObserver.observe(sensorManager); - mUdfpsObserver.observe(); synchronized (mLock) { // We may have a listener already registered before the call to start, so go ahead and // notify them to pick up our newly initialized state. @@ -163,6 +162,16 @@ public class DisplayModeDirector { } } + /** + * Same as {@link #start(SensorManager)}, but for observers that need to be delayed even more, + * for example until SystemUI is ready. + */ + public void onBootCompleted() { + // UDFPS observer registers a listener with SystemUI which might not be ready until the + // system is fully booted. + mUdfpsObserver.observe(); + } + public void setLoggingEnabled(boolean loggingEnabled) { if (mLoggingEnabled == loggingEnabled) { return; diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java index 52b05f2d112f..1b50f0388f9d 100644 --- a/services/core/java/com/android/server/display/DisplayPowerController.java +++ b/services/core/java/com/android/server/display/DisplayPowerController.java @@ -365,7 +365,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call @Nullable private final ColorDisplayServiceInternal mCdsi; - private final float[] mNitsRange; + private float[] mNitsRange; private final HighBrightnessModeController mHbmController; @@ -447,6 +447,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call mLogicalDisplay = logicalDisplay; mDisplayId = mLogicalDisplay.getDisplayIdLocked(); mDisplayDevice = mLogicalDisplay.getPrimaryDisplayDeviceLocked(); + mUniqueDisplayId = logicalDisplay.getPrimaryDisplayDeviceLocked().getUniqueId(); mHandler = new DisplayControllerHandler(handler.getLooper()); if (mDisplayId == Display.DEFAULT_DISPLAY) { @@ -462,6 +463,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call mBlanker = blanker; mContext = context; mBrightnessTracker = brightnessTracker; + // TODO: b/186428377 update brightness setting when display changes mBrightnessSetting = brightnessSetting; mOnBrightnessChangeRunnable = onBrightnessChangeRunnable; @@ -498,13 +500,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call mAllowAutoBrightnessWhileDozingConfig = resources.getBoolean( com.android.internal.R.bool.config_allowAutoBrightnessWhileDozing); + mDisplayDeviceConfig = logicalDisplay.getPrimaryDisplayDeviceLocked() + .getDisplayDeviceConfig(); - mDisplayDeviceConfig = logicalDisplay - .getPrimaryDisplayDeviceLocked().getDisplayDeviceConfig(); - mBrightnessRampRateFastDecrease = mDisplayDeviceConfig.getBrightnessRampFastDecrease(); - mBrightnessRampRateFastIncrease = mDisplayDeviceConfig.getBrightnessRampFastIncrease(); - mBrightnessRampRateSlowDecrease = mDisplayDeviceConfig.getBrightnessRampSlowDecrease(); - mBrightnessRampRateSlowIncrease = mDisplayDeviceConfig.getBrightnessRampSlowIncrease(); + loadBrightnessRampRates(); mSkipScreenOnBrightnessRamp = resources.getBoolean( com.android.internal.R.bool.config_skipScreenOnBrightnessRamp); @@ -513,66 +512,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call // Seed the cached brightness saveBrightnessInfo(getScreenBrightnessSetting()); - if (mUseSoftwareAutoBrightnessConfig) { - final float dozeScaleFactor = resources.getFraction( - com.android.internal.R.fraction.config_screenAutoBrightnessDozeScaleFactor, - 1, 1); - - int[] ambientBrighteningThresholds = resources.getIntArray( - com.android.internal.R.array.config_ambientBrighteningThresholds); - int[] ambientDarkeningThresholds = resources.getIntArray( - com.android.internal.R.array.config_ambientDarkeningThresholds); - int[] ambientThresholdLevels = resources.getIntArray( - com.android.internal.R.array.config_ambientThresholdLevels); - HysteresisLevels ambientBrightnessThresholds = new HysteresisLevels( - ambientBrighteningThresholds, ambientDarkeningThresholds, - ambientThresholdLevels); - - int[] screenBrighteningThresholds = resources.getIntArray( - com.android.internal.R.array.config_screenBrighteningThresholds); - int[] screenDarkeningThresholds = resources.getIntArray( - com.android.internal.R.array.config_screenDarkeningThresholds); - int[] screenThresholdLevels = resources.getIntArray( - com.android.internal.R.array.config_screenThresholdLevels); - HysteresisLevels screenBrightnessThresholds = new HysteresisLevels( - screenBrighteningThresholds, screenDarkeningThresholds, screenThresholdLevels); - - long brighteningLightDebounce = resources.getInteger( - com.android.internal.R.integer.config_autoBrightnessBrighteningLightDebounce); - long darkeningLightDebounce = resources.getInteger( - com.android.internal.R.integer.config_autoBrightnessDarkeningLightDebounce); - boolean autoBrightnessResetAmbientLuxAfterWarmUp = resources.getBoolean( - com.android.internal.R.bool.config_autoBrightnessResetAmbientLuxAfterWarmUp); - - int lightSensorWarmUpTimeConfig = resources.getInteger( - com.android.internal.R.integer.config_lightSensorWarmupTime); - int lightSensorRate = resources.getInteger( - com.android.internal.R.integer.config_autoBrightnessLightSensorRate); - int initialLightSensorRate = resources.getInteger( - com.android.internal.R.integer.config_autoBrightnessInitialLightSensorRate); - if (initialLightSensorRate == -1) { - initialLightSensorRate = lightSensorRate; - } else if (initialLightSensorRate > lightSensorRate) { - Slog.w(TAG, "Expected config_autoBrightnessInitialLightSensorRate (" - + initialLightSensorRate + ") to be less than or equal to " - + "config_autoBrightnessLightSensorRate (" + lightSensorRate + ")."); - } - - loadAmbientLightSensor(); - - mBrightnessMapper = BrightnessMappingStrategy.create(resources, mDisplayDeviceConfig); - if (mBrightnessMapper != null) { - mAutomaticBrightnessController = new AutomaticBrightnessController(this, - handler.getLooper(), sensorManager, mLightSensor, mBrightnessMapper, - lightSensorWarmUpTimeConfig, PowerManager.BRIGHTNESS_MIN, - PowerManager.BRIGHTNESS_MAX, dozeScaleFactor, lightSensorRate, - initialLightSensorRate, brighteningLightDebounce, darkeningLightDebounce, - autoBrightnessResetAmbientLuxAfterWarmUp, ambientBrightnessThresholds, - screenBrightnessThresholds, logicalDisplay, context, mHbmController); - } else { - mUseSoftwareAutoBrightnessConfig = false; - } - } + setUpAutoBrightness(resources, handler); mColorFadeEnabled = !ActivityManager.isLowRamDeviceStatic(); mColorFadeFadesConfig = resources.getBoolean( @@ -610,13 +550,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call mDisplayWhiteBalanceSettings = displayWhiteBalanceSettings; mDisplayWhiteBalanceController = displayWhiteBalanceController; - if (mDisplayDeviceConfig != null && mDisplayDeviceConfig.getNits() != null) { - mNitsRange = mDisplayDeviceConfig.getNits(); - } else { - Slog.w(TAG, "Screen brightness nits configuration is unavailable; falling back"); - mNitsRange = BrightnessMappingStrategy.getFloatArray(context.getResources() - .obtainTypedArray(com.android.internal.R.array.config_screenBrightnessNits)); - } + loadNitsRange(resources); + if (mDisplayId == Display.DEFAULT_DISPLAY) { mCdsi = LocalServices.getService(ColorDisplayServiceInternal.class); boolean active = mCdsi.setReduceBrightColorsListener(new ReduceBrightColorsListener() { @@ -802,10 +737,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call mDisplayDevice = device; mUniqueDisplayId = uniqueId; mDisplayDeviceConfig = config; - - loadAmbientLightSensor(); - loadProximitySensor(); - mHbmController.resetHbmData(token, config.getHighBrightnessModeData()); + loadFromDisplayDeviceConfig(token); }); } @@ -846,6 +778,18 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call } } + private void loadFromDisplayDeviceConfig(IBinder token) { + // All properties that depend on the associated DisplayDevice and the DDC must be + // updated here. + loadAmbientLightSensor(); + loadBrightnessRampRates(); + loadProximitySensor(); + loadNitsRange(mContext.getResources()); + setUpAutoBrightness(mContext.getResources(), mHandler); + reloadReduceBrightColours(); + mHbmController.resetHbmData(token, mDisplayDeviceConfig.getHighBrightnessModeData()); + } + private void sendUpdatePowerState() { synchronized (mLock) { sendUpdatePowerStateLocked(); @@ -903,6 +847,98 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call false /*notifyForDescendants*/, mSettingsObserver, UserHandle.USER_ALL); } + private void setUpAutoBrightness(Resources resources, Handler handler) { + if (!mUseSoftwareAutoBrightnessConfig) { + return; + } + + mBrightnessMapper = BrightnessMappingStrategy.create(resources, mDisplayDeviceConfig); + + if (mBrightnessMapper != null) { + final float dozeScaleFactor = resources.getFraction( + com.android.internal.R.fraction.config_screenAutoBrightnessDozeScaleFactor, + 1, 1); + + int[] ambientBrighteningThresholds = resources.getIntArray( + com.android.internal.R.array.config_ambientBrighteningThresholds); + int[] ambientDarkeningThresholds = resources.getIntArray( + com.android.internal.R.array.config_ambientDarkeningThresholds); + int[] ambientThresholdLevels = resources.getIntArray( + com.android.internal.R.array.config_ambientThresholdLevels); + HysteresisLevels ambientBrightnessThresholds = new HysteresisLevels( + ambientBrighteningThresholds, ambientDarkeningThresholds, + ambientThresholdLevels); + + int[] screenBrighteningThresholds = resources.getIntArray( + com.android.internal.R.array.config_screenBrighteningThresholds); + int[] screenDarkeningThresholds = resources.getIntArray( + com.android.internal.R.array.config_screenDarkeningThresholds); + int[] screenThresholdLevels = resources.getIntArray( + com.android.internal.R.array.config_screenThresholdLevels); + HysteresisLevels screenBrightnessThresholds = new HysteresisLevels( + screenBrighteningThresholds, screenDarkeningThresholds, screenThresholdLevels); + + long brighteningLightDebounce = resources.getInteger( + com.android.internal.R.integer.config_autoBrightnessBrighteningLightDebounce); + long darkeningLightDebounce = resources.getInteger( + com.android.internal.R.integer.config_autoBrightnessDarkeningLightDebounce); + boolean autoBrightnessResetAmbientLuxAfterWarmUp = resources.getBoolean( + com.android.internal.R.bool.config_autoBrightnessResetAmbientLuxAfterWarmUp); + + int lightSensorWarmUpTimeConfig = resources.getInteger( + com.android.internal.R.integer.config_lightSensorWarmupTime); + int lightSensorRate = resources.getInteger( + com.android.internal.R.integer.config_autoBrightnessLightSensorRate); + int initialLightSensorRate = resources.getInteger( + com.android.internal.R.integer.config_autoBrightnessInitialLightSensorRate); + if (initialLightSensorRate == -1) { + initialLightSensorRate = lightSensorRate; + } else if (initialLightSensorRate > lightSensorRate) { + Slog.w(TAG, "Expected config_autoBrightnessInitialLightSensorRate (" + + initialLightSensorRate + ") to be less than or equal to " + + "config_autoBrightnessLightSensorRate (" + lightSensorRate + ")."); + } + + loadAmbientLightSensor(); + + if (mAutomaticBrightnessController != null) { + mAutomaticBrightnessController.stop(); + } + mAutomaticBrightnessController = new AutomaticBrightnessController(this, + handler.getLooper(), mSensorManager, mLightSensor, mBrightnessMapper, + lightSensorWarmUpTimeConfig, PowerManager.BRIGHTNESS_MIN, + PowerManager.BRIGHTNESS_MAX, dozeScaleFactor, lightSensorRate, + initialLightSensorRate, brighteningLightDebounce, darkeningLightDebounce, + autoBrightnessResetAmbientLuxAfterWarmUp, ambientBrightnessThresholds, + screenBrightnessThresholds, mLogicalDisplay, mContext, mHbmController); + } else { + mUseSoftwareAutoBrightnessConfig = false; + } + } + + private void loadBrightnessRampRates() { + mBrightnessRampRateFastDecrease = mDisplayDeviceConfig.getBrightnessRampFastDecrease(); + mBrightnessRampRateFastIncrease = mDisplayDeviceConfig.getBrightnessRampFastIncrease(); + mBrightnessRampRateSlowDecrease = mDisplayDeviceConfig.getBrightnessRampSlowDecrease(); + mBrightnessRampRateSlowIncrease = mDisplayDeviceConfig.getBrightnessRampSlowIncrease(); + } + + private void loadNitsRange(Resources resources) { + if (mDisplayDeviceConfig != null && mDisplayDeviceConfig.getNits() != null) { + mNitsRange = mDisplayDeviceConfig.getNits(); + } else { + Slog.w(TAG, "Screen brightness nits configuration is unavailable; falling back"); + mNitsRange = BrightnessMappingStrategy.getFloatArray(resources + .obtainTypedArray(com.android.internal.R.array.config_screenBrightnessNits)); + } + } + + private void reloadReduceBrightColours() { + if (mCdsi != null && mCdsi.isReduceBrightColorsActivated()) { + applyReduceBrightColorsSplineAdjustment(); + } + } + private final Animator.AnimatorListener mAnimatorListener = new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { @@ -941,6 +977,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call final boolean mustNotify; final int previousPolicy; boolean mustInitialize = false; + boolean shouldSaveBrightnessInfo = true; int brightnessAdjustmentFlags = 0; mBrightnessReasonTemp.set(null); synchronized (mLock) { @@ -1071,6 +1108,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call 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 +1235,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call && Display.isDozeState(state)) { brightnessState = mScreenBrightnessDozeConfig; mBrightnessReasonTemp.setReason(BrightnessReason.REASON_DOZE_DEFAULT); + shouldSaveBrightnessInfo = false; } // Apply manual brightness. @@ -1213,7 +1252,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call // 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 a7e1a2876f81..6db75eb80aea 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 @@ final class WifiDisplayController implements DumpUtils.Dump { 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/LocationManagerService.java b/services/core/java/com/android/server/location/LocationManagerService.java index b9e97e89051b..aeb1893c78b6 100644 --- a/services/core/java/com/android/server/location/LocationManagerService.java +++ b/services/core/java/com/android/server/location/LocationManagerService.java @@ -65,7 +65,7 @@ import android.location.LastLocationRequest; import android.location.Location; import android.location.LocationManager; import android.location.LocationManagerInternal; -import android.location.LocationManagerInternal.OnProviderLocationTagsChangeListener; +import android.location.LocationManagerInternal.LocationPackageTagsListener; import android.location.LocationProvider; import android.location.LocationRequest; import android.location.LocationTime; @@ -93,6 +93,7 @@ import android.util.Log; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.DumpUtils; import com.android.internal.util.Preconditions; +import com.android.server.FgThread; import com.android.server.LocalServices; import com.android.server.SystemService; import com.android.server.location.eventlog.LocationEventLog; @@ -259,7 +260,7 @@ public class LocationManagerService extends ILocationManager.Stub implements new CopyOnWriteArrayList<>(); @GuardedBy("mLock") - @Nullable OnProviderLocationTagsChangeListener mOnProviderLocationTagsChangeListener; + @Nullable LocationPackageTagsListener mLocationTagsChangedListener; LocationManagerService(Context context, Injector injector) { mContext = context.createAttributionContext(ATTRIBUTION_TAG); @@ -1363,32 +1364,28 @@ public class LocationManagerService extends ILocationManager.Stub implements refreshAppOpsRestrictions(UserHandle.USER_ALL); } - OnProviderLocationTagsChangeListener listener; - synchronized (mLock) { - listener = mOnProviderLocationTagsChangeListener; - } - - if (listener != null) { - if (!oldState.extraAttributionTags.equals(newState.extraAttributionTags) - || !Objects.equals(oldState.identity, newState.identity)) { - if (oldState.identity != null) { - listener.onLocationTagsChanged( - new LocationManagerInternal.LocationTagInfo( - oldState.identity.getUid(), - oldState.identity.getPackageName(), - Collections.emptySet())); - } - if (newState.identity != null) { - ArraySet<String> attributionTags = new ArraySet<>( - newState.extraAttributionTags.size() + 1); - attributionTags.addAll(newState.extraAttributionTags); - attributionTags.add(newState.identity.getAttributionTag()); - - listener.onLocationTagsChanged( - new LocationManagerInternal.LocationTagInfo( - newState.identity.getUid(), - newState.identity.getPackageName(), - attributionTags)); + if (!oldState.extraAttributionTags.equals(newState.extraAttributionTags) + || !Objects.equals(oldState.identity, newState.identity)) { + // since we're potentially affecting the tag lists for two different uids, acquire the + // lock to ensure providers cannot change while we're looping over the providers + // multiple times, which could lead to inconsistent results. + synchronized (mLock) { + LocationPackageTagsListener listener = mLocationTagsChangedListener; + if (listener != null) { + int oldUid = oldState.identity != null ? oldState.identity.getUid() : -1; + int newUid = newState.identity != null ? newState.identity.getUid() : -1; + if (oldUid != -1) { + PackageTagsList tags = calculateAppOpsLocationSourceTags(oldUid); + FgThread.getHandler().post( + () -> listener.onLocationPackageTagsChanged(oldUid, tags)); + } + // if the new app id is the same as the old app id, no need to invoke the + // listener twice, it's already been taken care of + if (newUid != -1 && newUid != oldUid) { + PackageTagsList tags = calculateAppOpsLocationSourceTags(newUid); + FgThread.getHandler().post( + () -> listener.onLocationPackageTagsChanged(newUid, tags)); + } } } } @@ -1436,6 +1433,31 @@ public class LocationManagerService extends ILocationManager.Stub implements userId); } + PackageTagsList calculateAppOpsLocationSourceTags(int uid) { + PackageTagsList.Builder builder = new PackageTagsList.Builder(); + for (LocationProviderManager manager : mProviderManagers) { + AbstractLocationProvider.State managerState = manager.getState(); + if (managerState.identity == null) { + continue; + } + if (managerState.identity.getUid() != uid) { + continue; + } + + builder.add(managerState.identity.getPackageName(), managerState.extraAttributionTags); + if (managerState.extraAttributionTags.isEmpty() + || managerState.identity.getAttributionTag() != null) { + builder.add(managerState.identity.getPackageName(), + managerState.identity.getAttributionTag()); + } else { + Log.e(TAG, manager.getName() + " provider has specified a null attribution tag and " + + "a non-empty set of extra attribution tags - dropping the null " + + "attribution tag"); + } + } + return builder.build(); + } + private class LocalService extends LocationManagerInternal { LocalService() {} @@ -1506,10 +1528,29 @@ public class LocationManagerService extends ILocationManager.Stub implements } @Override - public void setOnProviderLocationTagsChangeListener( - @Nullable OnProviderLocationTagsChangeListener listener) { + public void setLocationPackageTagsListener( + @Nullable LocationPackageTagsListener listener) { synchronized (mLock) { - mOnProviderLocationTagsChangeListener = listener; + mLocationTagsChangedListener = listener; + + // calculate initial tag list and send to listener + if (listener != null) { + ArraySet<Integer> uids = new ArraySet<>(mProviderManagers.size()); + for (LocationProviderManager manager : mProviderManagers) { + CallerIdentity identity = manager.getIdentity(); + if (identity != null) { + uids.add(identity.getUid()); + } + } + + for (int uid : uids) { + PackageTagsList tags = calculateAppOpsLocationSourceTags(uid); + if (!tags.isEmpty()) { + FgThread.getHandler().post( + () -> listener.onLocationPackageTagsChanged(uid, tags)); + } + } + } } } } 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 5ec85e661b98..6931baa948a1 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 @@ public class ContextHubShellCommand extends ShellCommand { // 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/eventlog/LocationEventLog.java b/services/core/java/com/android/server/location/eventlog/LocationEventLog.java index 66b23c4d7377..e6d25ece93ef 100644 --- a/services/core/java/com/android/server/location/eventlog/LocationEventLog.java +++ b/services/core/java/com/android/server/location/eventlog/LocationEventLog.java @@ -33,7 +33,6 @@ import android.annotation.Nullable; import android.location.LocationRequest; import android.location.provider.ProviderRequest; import android.location.util.identity.CallerIdentity; -import android.os.Build; import android.os.PowerManager.LocationPowerSaveMode; import android.os.SystemClock; import android.util.ArrayMap; @@ -47,8 +46,8 @@ public class LocationEventLog extends LocalEventLog { public static final LocationEventLog EVENT_LOG = new LocationEventLog(); private static int getLogSize() { - if (Build.IS_DEBUGGABLE || D) { - return 500; + if (D) { + return 600; } else { return 200; } @@ -152,7 +151,7 @@ public class LocationEventLog extends LocalEventLog { /** Logs a client for a location provider entering the foreground state. */ public void logProviderClientForeground(String provider, CallerIdentity identity) { - if (Build.IS_DEBUGGABLE || D) { + if (D) { addLogEvent(EVENT_PROVIDER_CLIENT_FOREGROUND, provider, identity); } getAggregateStats(provider, identity).markRequestForeground(); @@ -160,7 +159,7 @@ public class LocationEventLog extends LocalEventLog { /** Logs a client for a location provider leaving the foreground state. */ public void logProviderClientBackground(String provider, CallerIdentity identity) { - if (Build.IS_DEBUGGABLE || D) { + if (D) { addLogEvent(EVENT_PROVIDER_CLIENT_BACKGROUND, provider, identity); } getAggregateStats(provider, identity).markRequestBackground(); @@ -168,14 +167,14 @@ public class LocationEventLog extends LocalEventLog { /** Logs a client for a location provider entering the permitted state. */ public void logProviderClientPermitted(String provider, CallerIdentity identity) { - if (Build.IS_DEBUGGABLE || D) { + if (D) { addLogEvent(EVENT_PROVIDER_CLIENT_PERMITTED, provider, identity); } } /** Logs a client for a location provider leaving the permitted state. */ public void logProviderClientUnpermitted(String provider, CallerIdentity identity) { - if (Build.IS_DEBUGGABLE || D) { + if (D) { addLogEvent(EVENT_PROVIDER_CLIENT_UNPERMITTED, provider, identity); } } @@ -187,7 +186,7 @@ public class LocationEventLog extends LocalEventLog { /** Logs a new incoming location for a location provider. */ public void logProviderReceivedLocations(String provider, int numLocations) { - if (Build.IS_DEBUGGABLE || D) { + if (D) { addLogEvent(EVENT_PROVIDER_RECEIVE_LOCATION, provider, numLocations); } } @@ -195,7 +194,7 @@ public class LocationEventLog extends LocalEventLog { /** Logs a location deliver for a client of a location provider. */ public void logProviderDeliveredLocations(String provider, int numLocations, CallerIdentity identity) { - if (Build.IS_DEBUGGABLE || D) { + if (D) { addLogEvent(EVENT_PROVIDER_DELIVER_LOCATION, provider, numLocations, identity); } getAggregateStats(provider, identity).markLocationDelivered(); 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 ba7f44f2818b..eb7b77a2234f 100644 --- a/services/core/java/com/android/server/location/provider/AbstractLocationProvider.java +++ b/services/core/java/com/android/server/location/provider/AbstractLocationProvider.java @@ -263,10 +263,10 @@ public abstract class AbstractLocationProvider { } /** - * The current allowed state of this provider. + * The current state of the provider. */ - public final boolean isAllowed() { - return mInternalState.get().state.allowed; + public final State getState() { + return mInternalState.get().state; } /** @@ -277,13 +277,6 @@ public abstract class AbstractLocationProvider { } /** - * The current provider properties of this provider. - */ - public final @Nullable ProviderProperties getProperties() { - return mInternalState.get().state.properties; - } - - /** * Call this method to report a change in provider properties. */ protected void setProperties(@Nullable ProviderProperties properties) { @@ -291,13 +284,6 @@ public abstract class AbstractLocationProvider { } /** - * The current identity of this provider. - */ - public final @Nullable CallerIdentity getIdentity() { - return mInternalState.get().state.identity; - } - - /** * Call this method to report a change in the provider's identity. */ protected void setIdentity(@Nullable CallerIdentity identity) { @@ -305,6 +291,10 @@ public abstract class AbstractLocationProvider { 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/LocationProviderManager.java b/services/core/java/com/android/server/location/provider/LocationProviderManager.java index 4f8b87b51294..8d335b83d99c 100644 --- a/services/core/java/com/android/server/location/provider/LocationProviderManager.java +++ b/services/core/java/com/android/server/location/provider/LocationProviderManager.java @@ -1407,12 +1407,16 @@ public class LocationProviderManager extends return mName; } + public AbstractLocationProvider.State getState() { + return mProvider.getState(); + } + public @Nullable CallerIdentity getIdentity() { - return mProvider.getIdentity(); + return mProvider.getState().identity; } public @Nullable ProviderProperties getProperties() { - return mProvider.getProperties(); + return mProvider.getState().properties; } public boolean hasProvider() { @@ -2403,7 +2407,7 @@ public class LocationProviderManager extends Preconditions.checkArgument(userId >= 0); boolean enabled = mState == STATE_STARTED - && mProvider.isAllowed() + && mProvider.getState().allowed && mSettingsHelper.isLocationEnabled(userId); int index = mEnabled.indexOfKey(userId); 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 81936440f6a7..22295fe7ba28 100644 --- a/services/core/java/com/android/server/location/provider/MockableLocationProvider.java +++ b/services/core/java/com/android/server/location/provider/MockableLocationProvider.java @@ -21,9 +21,7 @@ import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR; import android.annotation.Nullable; import android.location.Location; import android.location.LocationResult; -import android.location.provider.ProviderProperties; import android.location.provider.ProviderRequest; -import android.location.util.identity.CallerIdentity; import android.os.Bundle; import com.android.internal.annotations.GuardedBy; @@ -289,17 +287,21 @@ public class MockableLocationProvider extends AbstractLocationProvider { Preconditions.checkState(!Thread.holdsLock(mOwnerLock)); AbstractLocationProvider provider; + State providerState; synchronized (mOwnerLock) { provider = mProvider; - pw.println("allowed=" + isAllowed()); - CallerIdentity identity = getIdentity(); - if (identity != null) { - pw.println("identity=" + identity); - } - ProviderProperties properties = getProperties(); - if (properties != null) { - pw.println("properties=" + properties); - } + providerState = getState(); + } + + pw.println("allowed=" + providerState.allowed); + if (providerState.identity != null) { + pw.println("identity=" + providerState.identity); + } + if (!providerState.extraAttributionTags.isEmpty()) { + pw.println("extra attribution tags=" + providerState.extraAttributionTags); + } + if (providerState.properties != null) { + pw.println("properties=" + providerState.properties); } if (provider != null) { 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 5df78704d002..a9641f0f1c1b 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.IBinder; 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 com.android.server.servicewatcher.ServiceWatcher.ServiceListener; 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 @@ public class ProxyLocationProvider extends AbstractLocationProvider implements final Context mContext; final ServiceWatcher mServiceWatcher; + final String mName; @GuardedBy("mLock") final ArrayList<Runnable> mFlushListeners = new ArrayList<>(0); @@ -101,6 +105,7 @@ public class ProxyLocationProvider extends AbstractLocationProvider implements mServiceWatcher = ServiceWatcher.create(context, provider, new CurrentUserServiceSupplier(context, action, enableOverlayResId, nonOverlayPackageResId), this); + mName = provider; mProxy = null; mRequest = ProviderRequest.EMPTY_REQUEST; @@ -249,6 +254,8 @@ public class ProxyLocationProvider extends AbstractLocationProvider implements 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/metrics/MediaMetricsManagerService.java b/services/core/java/com/android/server/media/metrics/MediaMetricsManagerService.java index 1e0142c496b0..2cc2ebf616c5 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 @@ public final class MediaMetricsManagerService extends SystemService { 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 4b4146683a09..654b17fb9754 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_POWERSAVE; 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 @@ public class NetworkPolicyLogger { } } - 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 @@ public class NetworkPolicyLogger { 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 @@ public class NetworkPolicyLogger { 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 @@ public class NetworkPolicyLogger { 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 2e4d41c7d364..03a63b9058a8 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 @@ public abstract class NetworkPolicyManagerInternal { * 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 cfd575080d97..21f68aecd25b 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.Message; 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 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } @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 5b5d5d403cb7..b26485b5aad9 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 @@ public class NotificationManagerService extends SystemService { 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 b0be20698005..fc106b8ec4ac 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.content.pm.ShortcutServiceInternal; 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 @@ public class ShortcutHelper { 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 @@ public class ShortcutHelper { }; ShortcutHelper(LauncherApps launcherApps, ShortcutListener listener, - ShortcutServiceInternal shortcutServiceInternal) { + ShortcutServiceInternal shortcutServiceInternal, UserManager userManager) { mLauncherAppsService = launcherApps; mShortcutListener = listener; mShortcutServiceInternal = shortcutServiceInternal; + mUserManager = userManager; } @VisibleForTesting @@ -160,6 +163,11 @@ public class ShortcutHelper { mShortcutServiceInternal = shortcutServiceInternal; } + @VisibleForTesting + void setUserManager(UserManager userManager) { + mUserManager = userManager; + } + /** * Returns whether the given shortcut info is a conversation shortcut. */ @@ -182,7 +190,8 @@ public class ShortcutHelper { * 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/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java index 9370b14341dc..5b2c80903ce5 100644 --- a/services/core/java/com/android/server/pm/LauncherAppsService.java +++ b/services/core/java/com/android/server/pm/LauncherAppsService.java @@ -1000,16 +1000,15 @@ public class LauncherAppsService extends SystemService { intents[0].setSourceBounds(sourceBounds); // Replace theme for splash screen - final int splashScreenThemeResId = - mShortcutServiceInternal.getShortcutStartingThemeResId(getCallingUserId(), + final String splashScreenThemeResName = + mShortcutServiceInternal.getShortcutStartingThemeResName(getCallingUserId(), callingPackage, packageName, shortcutId, targetUserId); - if (splashScreenThemeResId != 0) { + if (splashScreenThemeResName != null && !splashScreenThemeResName.isEmpty()) { if (startActivityOptions == null) { startActivityOptions = new Bundle(); } - startActivityOptions.putInt(KEY_SPLASH_SCREEN_THEME, splashScreenThemeResId); + startActivityOptions.putString(KEY_SPLASH_SCREEN_THEME, splashScreenThemeResName); } - return startShortcutIntentsAsPublisher( intents, packageName, featureId, startActivityOptions, targetUserId); } diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java index 0b63b7ddef85..60a757118222 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerService.java +++ b/services/core/java/com/android/server/pm/PackageInstallerService.java @@ -626,7 +626,14 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements } boolean isApex = (params.installFlags & PackageManager.INSTALL_APEX) != 0; - if (params.isStaged || isApex) { + if (isApex) { + if (mContext.checkCallingOrSelfPermission(Manifest.permission.INSTALL_PACKAGE_UPDATES) + == PackageManager.PERMISSION_DENIED + && mContext.checkCallingOrSelfPermission(Manifest.permission.INSTALL_PACKAGES) + == PackageManager.PERMISSION_DENIED) { + throw new SecurityException("Not allowed to perform APEX updates"); + } + } else if (params.isStaged) { mContext.enforceCallingOrSelfPermission(Manifest.permission.INSTALL_PACKAGES, TAG); } @@ -1110,6 +1117,17 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements mSilentUpdatePolicy.setAllowUnlimitedSilentUpdates(installerPackageName); } + /** + * Set the silent updates throttle time in seconds. + */ + @Override + public void setSilentUpdatesThrottleTime(long throttleTimeInSeconds) { + if (!isCalledBySystemOrShell(Binder.getCallingUid())) { + throw new SecurityException("Caller not allowed to set silent updates throttle time"); + } + mSilentUpdatePolicy.setSilentUpdatesThrottleTime(throttleTimeInSeconds); + } + private static int getSessionCount(SparseArray<PackageInstallerSession> sessions, int installerUid) { int count = 0; diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index 8202587ecf53..4b0eb6546888 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 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { 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 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { (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 c812fc8b7081..a8cc5fdf884d 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -23607,11 +23607,6 @@ public class PackageManagerService extends IPackageManager.Stub 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(); @@ -23643,6 +23638,10 @@ public class PackageManagerService extends IPackageManager.Stub "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 diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java index f9c63a948a86..49559f299fa0 100644 --- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java +++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java @@ -307,8 +307,8 @@ class PackageManagerShellCommand extends ShellCommand { return runLogVisibility(); case "bypass-staged-installer-check": return runBypassStagedInstallerCheck(); - case "allow-unlimited-silent-updates": - return runAllowUnlimitedSilentUpdates(); + case "set-silent-updates-policy": + return runSetSilentUpdatesPolicy(); default: { Boolean domainVerificationResult = mDomainVerificationShell.runCommand(this, cmd); @@ -3041,12 +3041,20 @@ class PackageManagerShellCommand extends ShellCommand { } } - private int runAllowUnlimitedSilentUpdates() { + private int runSetSilentUpdatesPolicy() { final PrintWriter pw = getOutPrintWriter(); String opt; + String installerPackageName = null; + Long throttleTimeInSeconds = null; boolean reset = false; while ((opt = getNextOption()) != null) { switch (opt) { + case "--allow-unlimited-silent-updates": + installerPackageName = getNextArgRequired(); + break; + case "--throttle-time": + throttleTimeInSeconds = Long.parseLong(getNextArgRequired()); + break; case "--reset": reset = true; break; @@ -3055,10 +3063,24 @@ class PackageManagerShellCommand extends ShellCommand { return -1; } } + if (throttleTimeInSeconds != null && throttleTimeInSeconds < 0) { + pw.println("Error: Invalid value for \"--throttle-time\":" + throttleTimeInSeconds); + return -1; + } - final String installerPackageName = reset ? null : getNextArgRequired(); try { - mInterface.getPackageInstaller().setAllowUnlimitedSilentUpdates(installerPackageName); + final IPackageInstaller installer = mInterface.getPackageInstaller(); + if (reset) { + installer.setAllowUnlimitedSilentUpdates(null /* installerPackageName */); + installer.setSilentUpdatesThrottleTime(-1 /* restore to the default */); + } else { + if (installerPackageName != null) { + installer.setAllowUnlimitedSilentUpdates(installerPackageName); + } + if (throttleTimeInSeconds != null) { + installer.setSilentUpdatesThrottleTime(throttleTimeInSeconds); + } + } } catch (RemoteException e) { pw.println("Failure [" + e.getClass().getName() + " - " @@ -3889,11 +3911,14 @@ class PackageManagerShellCommand extends ShellCommand { pw.println(" --enable: turn on debug logging (default)"); pw.println(" --disable: turn off debug logging"); pw.println(""); - pw.println(" allow-unlimited-silent-updates (--reset | <INSTALLER>)"); - pw.println(" Allows unlimited silent updated installation requests from the installer"); - pw.println(" without the throttle time."); - pw.println(" --reset: clear the allowed installer and tracks of silent updates in"); - pw.println(" the system."); + pw.println(" set-silent-updates-policy [--allow-unlimited-silent-updates <INSTALLER>]"); + pw.println(" [--throttle-time <SECONDS>] [--reset]"); + pw.println(" Sets the policies of the silent updates."); + pw.println(" --allow-unlimited-silent-updates: allows unlimited silent updated"); + pw.println(" installation requests from the installer without the throttle time."); + pw.println(" --throttle-time: update the silent updates throttle time in seconds."); + pw.println(" --reset: restore the installer and throttle time to the default, and"); + pw.println(" clear tracks of silent updates in the system."); pw.println(""); mDomainVerificationShell.printHelp(pw); 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 4bc87a273084..7aa1c3ab8154 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 @@ public final class Settings implements Watchable, Snappable { 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 f411c98433cf..901f96f7054b 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 @@ public class ShortcutBitmapSaver { * 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 @@ public class ShortcutBitmapSaver { } 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 @@ public class ShortcutBitmapSaver { 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/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java index 1bd9e5eedb84..b4bd086af272 100644 --- a/services/core/java/com/android/server/pm/ShortcutPackage.java +++ b/services/core/java/com/android/server/pm/ShortcutPackage.java @@ -139,7 +139,7 @@ class ShortcutPackage extends ShortcutPackageItem { private static final String ATTR_BITMAP_PATH = "bitmap-path"; private static final String ATTR_ICON_URI = "icon-uri"; private static final String ATTR_LOCUS_ID = "locus-id"; - private static final String ATTR_SPLASH_SCREEN_THEME_ID = "splash-screen-theme-id"; + private static final String ATTR_SPLASH_SCREEN_THEME_NAME = "splash-screen-theme-name"; private static final String ATTR_PERSON_NAME = "name"; private static final String ATTR_PERSON_URI = "uri"; @@ -1799,7 +1799,7 @@ class ShortcutPackage extends ShortcutPackageItem { ShortcutService.writeAttr(out, ATTR_TITLE, si.getTitle()); ShortcutService.writeAttr(out, ATTR_TITLE_RES_ID, si.getTitleResId()); ShortcutService.writeAttr(out, ATTR_TITLE_RES_NAME, si.getTitleResName()); - ShortcutService.writeAttr(out, ATTR_SPLASH_SCREEN_THEME_ID, si.getStartingThemeResId()); + ShortcutService.writeAttr(out, ATTR_SPLASH_SCREEN_THEME_NAME, si.getStartingThemeResName()); ShortcutService.writeAttr(out, ATTR_TEXT, si.getText()); ShortcutService.writeAttr(out, ATTR_TEXT_RES_ID, si.getTextResId()); ShortcutService.writeAttr(out, ATTR_TEXT_RES_NAME, si.getTextResName()); @@ -2010,7 +2010,7 @@ class ShortcutPackage extends ShortcutPackageItem { String bitmapPath; String iconUri; final String locusIdString; - int splashScreenThemeResId; + String splashScreenThemeResName; int backupVersionCode; ArraySet<String> categories = null; ArrayList<Person> persons = new ArrayList<>(); @@ -2021,8 +2021,8 @@ class ShortcutPackage extends ShortcutPackageItem { title = ShortcutService.parseStringAttribute(parser, ATTR_TITLE); titleResId = ShortcutService.parseIntAttribute(parser, ATTR_TITLE_RES_ID); titleResName = ShortcutService.parseStringAttribute(parser, ATTR_TITLE_RES_NAME); - splashScreenThemeResId = ShortcutService.parseIntAttribute(parser, - ATTR_SPLASH_SCREEN_THEME_ID); + splashScreenThemeResName = ShortcutService.parseStringAttribute(parser, + ATTR_SPLASH_SCREEN_THEME_NAME); text = ShortcutService.parseStringAttribute(parser, ATTR_TEXT); textResId = ShortcutService.parseIntAttribute(parser, ATTR_TEXT_RES_ID); textResName = ShortcutService.parseStringAttribute(parser, ATTR_TEXT_RES_NAME); @@ -2117,7 +2117,7 @@ class ShortcutPackage extends ShortcutPackageItem { rank, extras, lastChangedTimestamp, flags, iconResId, iconResName, bitmapPath, iconUri, disabledReason, persons.toArray(new Person[persons.size()]), locusId, - splashScreenThemeResId); + splashScreenThemeResName); } private static Intent parseIntent(TypedXmlPullParser parser) diff --git a/services/core/java/com/android/server/pm/ShortcutParser.java b/services/core/java/com/android/server/pm/ShortcutParser.java index c06f01a463ad..b86c50b23687 100644 --- a/services/core/java/com/android/server/pm/ShortcutParser.java +++ b/services/core/java/com/android/server/pm/ShortcutParser.java @@ -383,8 +383,11 @@ public class ShortcutParser { final int textResId = sa.getResourceId(R.styleable.Shortcut_shortcutLongLabel, 0); final int disabledMessageResId = sa.getResourceId( R.styleable.Shortcut_shortcutDisabledMessage, 0); - final int splashScreenTheme = sa.getResourceId( + final int splashScreenThemeResId = sa.getResourceId( R.styleable.Shortcut_splashScreenTheme, 0); + final String splashScreenThemeResName = splashScreenThemeResId != 0 + ? service.mContext.getResources().getResourceName(splashScreenThemeResId) + : null; if (TextUtils.isEmpty(id)) { Log.w(TAG, "android:shortcutId must be provided. activity=" + activity); @@ -407,7 +410,7 @@ public class ShortcutParser { rank, iconResId, enabled, - splashScreenTheme); + splashScreenThemeResName); } finally { sa.recycle(); } @@ -416,7 +419,7 @@ public class ShortcutParser { private static ShortcutInfo createShortcutFromManifest(ShortcutService service, @UserIdInt int userId, String id, String packageName, ComponentName activityComponent, int titleResId, int textResId, int disabledMessageResId, - int rank, int iconResId, boolean enabled, int splashScreenTheme) { + int rank, int iconResId, boolean enabled, @Nullable String splashScreenThemeResName) { final int flags = (enabled ? ShortcutInfo.FLAG_MANIFEST : ShortcutInfo.FLAG_DISABLED) @@ -456,7 +459,7 @@ public class ShortcutParser { disabledReason, null /* persons */, null /* locusId */, - splashScreenTheme); + splashScreenThemeResName); } private static String parseCategory(ShortcutService service, AttributeSet attrs) { diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java index 1e9d7e1f8ad2..fcbf40e29933 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 @@ public class ShortcutService extends IShortcutService.Stub { } } - 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() { @@ -3546,7 +3536,8 @@ public class ShortcutService extends IShortcutService.Stub { } @Override - public int getShortcutStartingThemeResId(int launcherUserId, + @Nullable + public String getShortcutStartingThemeResName(int launcherUserId, @NonNull String callingPackage, @NonNull String packageName, @NonNull String shortcutId, int userId) { Objects.requireNonNull(callingPackage, "callingPackage"); @@ -3563,11 +3554,11 @@ public class ShortcutService extends IShortcutService.Stub { final ShortcutPackage p = getUserShortcutsLocked(userId) .getPackageShortcutsIfExists(packageName); if (p == null) { - return 0; + return null; } final ShortcutInfo shortcutInfo = p.findShortcutById(shortcutId); - return shortcutInfo != null ? shortcutInfo.getStartingThemeResId() : 0; + return shortcutInfo != null ? shortcutInfo.getStartingThemeResName() : null; } } diff --git a/services/core/java/com/android/server/pm/SilentUpdatePolicy.java b/services/core/java/com/android/server/pm/SilentUpdatePolicy.java index 117acab6d079..700f72cfbb94 100644 --- a/services/core/java/com/android/server/pm/SilentUpdatePolicy.java +++ b/services/core/java/com/android/server/pm/SilentUpdatePolicy.java @@ -33,7 +33,8 @@ import java.util.concurrent.TimeUnit; * in the {@link PackageInstallerSession}. */ public class SilentUpdatePolicy { - // A throttle time to prevent the installer from silently updating the same app repeatedly. + // The default throttle time to prevent the installer from silently updating the same app + // repeatedly. private static final long SILENT_UPDATE_THROTTLE_TIME_MS = TimeUnit.SECONDS.toMillis(30); // Map to the uptime timestamp for each installer and app of the silent update. @@ -44,6 +45,9 @@ public class SilentUpdatePolicy { @GuardedBy("mSilentUpdateInfos") private String mAllowUnlimitedSilentUpdatesInstaller; + @GuardedBy("mSilentUpdateInfos") + private long mSilentUpdateThrottleTimeMs = SILENT_UPDATE_THROTTLE_TIME_MS; + /** * Checks if the silent update is allowed by the given installer and app package name. * @@ -58,7 +62,11 @@ public class SilentUpdatePolicy { return true; } final long lastSilentUpdatedMs = getTimestampMs(installerPackageName, packageName); - return SystemClock.uptimeMillis() - lastSilentUpdatedMs > SILENT_UPDATE_THROTTLE_TIME_MS; + final long throttleTimeMs; + synchronized (mSilentUpdateInfos) { + throttleTimeMs = mSilentUpdateThrottleTimeMs; + } + return SystemClock.uptimeMillis() - lastSilentUpdatedMs > throttleTimeMs; } /** @@ -99,11 +107,25 @@ public class SilentUpdatePolicy { } } + /** + * Set the silent updates throttle time in seconds. + * + * @param throttleTimeInSeconds The throttle time to set, or <code>-1</code> to restore the + * value to the default. + */ + void setSilentUpdatesThrottleTime(long throttleTimeInSeconds) { + synchronized (mSilentUpdateInfos) { + mSilentUpdateThrottleTimeMs = throttleTimeInSeconds >= 0 + ? TimeUnit.SECONDS.toMillis(throttleTimeInSeconds) + : SILENT_UPDATE_THROTTLE_TIME_MS; + } + } + private void pruneLocked(long uptime) { final int size = mSilentUpdateInfos.size(); for (int i = size - 1; i >= 0; i--) { final long lastSilentUpdatedMs = mSilentUpdateInfos.valueAt(i); - if (uptime - lastSilentUpdatedMs > SILENT_UPDATE_THROTTLE_TIME_MS) { + if (uptime - lastSilentUpdatedMs > mSilentUpdateThrottleTimeMs) { mSilentUpdateInfos.removeAt(i); } } 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 92b6a0818de8..a391dbc1fa47 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.UserManagerInternal; 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 @@ public class PermissionManagerService extends IPermissionManager.Stub { @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 class PermissionManagerService extends IPermissionManager.Stub { 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 @@ public class PermissionManagerService extends IPermissionManager.Stub { 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,8 +5511,9 @@ public class PermissionManagerService extends IPermissionManager.Stub { 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 && result != PermissionChecker.PERMISSION_SOFT_DENIED) { @@ -5582,10 +5602,11 @@ public class PermissionManagerService extends IPermissionManager.Stub { } @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) { @@ -5602,22 +5623,25 @@ public class PermissionManagerService extends IPermissionManager.Stub { } 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; @@ -5625,6 +5649,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { @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); @@ -5668,13 +5693,13 @@ public class PermissionManagerService extends IPermissionManager.Stub { 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; } } @@ -5689,6 +5714,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { } 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) { @@ -5713,13 +5739,13 @@ public class PermissionManagerService extends IPermissionManager.Stub { } // 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; } @@ -5774,10 +5800,26 @@ public class PermissionManagerService extends IPermissionManager.Stub { } } - 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 895cabc33bab..f4fb8102d922 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 @@ public interface PermissionManagerServiceInternal extends PermissionManagerInter } } } + + /** + * 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/policy/AppOpsPolicy.java b/services/core/java/com/android/server/policy/AppOpsPolicy.java index 70b5c62a4973..22c370ef4dbe 100644 --- a/services/core/java/com/android/server/policy/AppOpsPolicy.java +++ b/services/core/java/com/android/server/policy/AppOpsPolicy.java @@ -33,11 +33,15 @@ import android.content.pm.ResolveInfo; import android.location.LocationManagerInternal; import android.net.Uri; import android.os.IBinder; +import android.os.PackageTagsList; +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; import android.util.Log; +import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.function.DecFunction; @@ -49,9 +53,9 @@ import com.android.internal.util.function.TriFunction; import com.android.internal.util.function.UndecFunction; import com.android.server.LocalServices; +import java.util.Arrays; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.concurrent.ConcurrentHashMap; /** @@ -64,11 +68,10 @@ public final class AppOpsPolicy implements AppOpsManagerInternal.CheckOpsDelegat "android:activity_recognition_allow_listed_tags"; private static final String ACTIVITY_RECOGNITION_TAGS_SEPARATOR = ";"; - private static ArraySet<String> sExpectedTags = new ArraySet<>(new String[] { + private static final 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(); @@ -78,6 +81,9 @@ public final class AppOpsPolicy implements AppOpsManagerInternal.CheckOpsDelegat @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 @@ -90,27 +96,53 @@ public final class AppOpsPolicy implements AppOpsManagerInternal.CheckOpsDelegat */ @GuardedBy("mLock - writes only - see above") @NonNull - private final ConcurrentHashMap<Integer, ArrayMap<String, ArraySet<String>>> mLocationTags = + private final ConcurrentHashMap<Integer, PackageTagsList> mLocationTags = new ConcurrentHashMap<>(); + // location tags can vary per uid - but we merge all tags under an app id into the final data + // structure above + @GuardedBy("mLock") + private final SparseArray<PackageTagsList> mPerUidLocationTags = new SparseArray<>(); + + // activity recognition currently only grabs tags from the APK manifest. we know that the + // manifest is the same for all users, so there's no need to track variations in tags across + // different users. if that logic ever changes, this might need to behave more like location + // tags above. @GuardedBy("mLock - writes only - see above") @NonNull - private final ConcurrentHashMap<Integer, ArrayMap<String, ArraySet<String>>> - mActivityRecognitionTags = new ConcurrentHashMap<>(); + private final ConcurrentHashMap<Integer, PackageTagsList> mActivityRecognitionTags = + new ConcurrentHashMap<>(); public AppOpsPolicy(@NonNull Context context) { mContext = context; mRoleManager = mContext.getSystemService(RoleManager.class); + mVoiceInteractionManagerInternal = LocalServices.getService( + VoiceInteractionManagerInternal.class); final LocationManagerInternal locationManagerInternal = LocalServices.getService( LocationManagerInternal.class); - locationManagerInternal.setOnProviderLocationTagsChangeListener((providerTagInfo) -> { - synchronized (mLock) { - updateAllowListedTagsForPackageLocked(providerTagInfo.getUid(), - providerTagInfo.getPackageName(), providerTagInfo.getTags(), - mLocationTags); - } - }); + locationManagerInternal.setLocationPackageTagsListener( + (uid, packageTagsList) -> { + synchronized (mLock) { + if (packageTagsList.isEmpty()) { + mPerUidLocationTags.remove(uid); + } else { + mPerUidLocationTags.set(uid, packageTagsList); + } + + int appId = UserHandle.getAppId(uid); + PackageTagsList.Builder appIdTags = new PackageTagsList.Builder(1); + int size = mPerUidLocationTags.size(); + for (int i = 0; i < size; i++) { + if (UserHandle.getAppId(mPerUidLocationTags.keyAt(i)) == appId) { + appIdTags.add(mPerUidLocationTags.valueAt(i)); + } + } + + updateAllowListedTagsForPackageLocked(appId, appIdTags.build(), + mLocationTags); + } + }); final IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED); @@ -150,7 +182,7 @@ public final class AppOpsPolicy implements AppOpsManagerInternal.CheckOpsDelegat 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 @@ -164,8 +196,8 @@ public final class AppOpsPolicy implements AppOpsManagerInternal.CheckOpsDelegat @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); } @@ -190,8 +222,9 @@ public final class AppOpsPolicy implements AppOpsManagerInternal.CheckOpsDelegat 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 @@ -297,95 +330,30 @@ public final class AppOpsPolicy implements AppOpsManagerInternal.CheckOpsDelegat } final String tagsList = resolvedService.serviceInfo.metaData.getString( ACTIVITY_RECOGNITION_TAGS); - if (tagsList != null) { - final String[] tags = tagsList.split(ACTIVITY_RECOGNITION_TAGS_SEPARATOR); + if (!TextUtils.isEmpty(tagsList)) { + PackageTagsList packageTagsList = new PackageTagsList.Builder(1).add( + resolvedService.serviceInfo.packageName, + Arrays.asList(tagsList.split(ACTIVITY_RECOGNITION_TAGS_SEPARATOR))).build(); synchronized (mLock) { updateAllowListedTagsForPackageLocked( - resolvedService.serviceInfo.applicationInfo.uid, - resolvedService.serviceInfo.packageName, new ArraySet<>(tags), + UserHandle.getAppId(resolvedService.serviceInfo.applicationInfo.uid), + packageTagsList, mActivityRecognitionTags); } } } - private static void updateAllowListedTagsForPackageLocked(int uid, String packageName, - Set<String> allowListedTags, ConcurrentHashMap<Integer, ArrayMap<String, - ArraySet<String>>> datastore) { - final int appId = UserHandle.getAppId(uid); - // We make a copy of the per UID state to limit our mutation to one - // operation in the underlying concurrent data structure. - ArrayMap<String, ArraySet<String>> appIdTags = datastore.get(appId); - if (appIdTags != null) { - appIdTags = new ArrayMap<>(appIdTags); - } - - ArraySet<String> packageTags = (appIdTags != null) ? appIdTags.get(packageName) : null; - if (packageTags != null) { - packageTags = new ArraySet<>(packageTags); - } - - if (allowListedTags != null && !allowListedTags.isEmpty()) { - if (packageTags != null) { - packageTags.clear(); - packageTags.addAll(allowListedTags); - } else { - packageTags = new ArraySet<>(allowListedTags); - } - if (appIdTags == null) { - appIdTags = new ArrayMap<>(); - } - - // Remove any invalid tags - boolean nullRemoved = packageTags.remove(null); - boolean nullStrRemoved = packageTags.remove("null"); - boolean emptyRemoved = packageTags.remove(""); - if (nullRemoved || nullStrRemoved || emptyRemoved) { - Log.e(LOG_TAG, "Attempted to add invalid source attribution tag, removed " - + "null: " + nullRemoved + " removed \"null\": " + nullStrRemoved - + " removed empty string: " + emptyRemoved); - } - - appIdTags.put(packageName, packageTags); - datastore.put(appId, appIdTags); - } else if (appIdTags != null) { - appIdTags.remove(packageName); - if (!appIdTags.isEmpty()) { - datastore.put(appId, appIdTags); - } else { - datastore.remove(appId); - } - } + private static void updateAllowListedTagsForPackageLocked(int appId, + PackageTagsList packageTagsList, + ConcurrentHashMap<Integer, PackageTagsList> datastore) { + datastore.put(appId, packageTagsList); } private static boolean isDatasourceAttributionTag(int uid, @NonNull String packageName, - @NonNull String attributionTag, @NonNull Map<Integer, ArrayMap<String, - ArraySet<String>>> mappedOps) { + @NonNull String attributionTag, @NonNull Map<Integer, PackageTagsList> mappedOps) { // Only a single lookup from the underlying concurrent data structure - final int appId = UserHandle.getAppId(uid); - final ArrayMap<String, ArraySet<String>> appIdTags = mappedOps.get(appId); - if (appIdTags != null) { - final ArraySet<String> packageTags = appIdTags.get(packageName); - if (packageTags != null && packageTags.contains(attributionTag)) { - 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") - && sExpectedTags.contains(attributionTag)) { - Log.i("AppOpsDebugRemapping", packageName + " tag " + attributionTag - + " NOT in " + packageTags); - } - } else { - if (packageName.equals("com.google.android.gms")) { - Log.i("AppOpsDebugRemapping", "no package tags for uid " + uid - + " package " + packageName); - } - - } - return false; + final PackageTagsList appIdTags = mappedOps.get(UserHandle.getAppId(uid)); + return appIdTags != null && appIdTags.contains(packageName, attributionTag); } private static int resolveLocationOp(int code) { @@ -404,4 +372,23 @@ public final class AppOpsPolicy implements AppOpsManagerInternal.CheckOpsDelegat } 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 f3b8c7e3e209..e6adeb3abab8 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 @@ public class PhoneWindowManager implements WindowManagerPolicy { 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 @@ public class PhoneWindowManager implements WindowManagerPolicy { 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 cdce660835b6..0535af57d8ab 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 @@ public class KeyguardServiceDelegate { */ @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 class KeyguardServiceDelegate { } 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 e718ba3b17cf..631be380e2eb 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 @@ class ServiceWatcherImpl<TBoundServiceInfo extends BoundServiceInfo> implements 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 @@ class ServiceWatcherImpl<TBoundServiceInfo extends BoundServiceInfo> implements 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 @@ class ServiceWatcherImpl<TBoundServiceInfo extends BoundServiceInfo> implements 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 @@ class ServiceWatcherImpl<TBoundServiceInfo extends BoundServiceInfo> implements 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 @@ class ServiceWatcherImpl<TBoundServiceInfo extends BoundServiceInfo> implements 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/vibrator/DeviceVibrationEffectAdapter.java b/services/core/java/com/android/server/vibrator/DeviceVibrationEffectAdapter.java index b695150d9ba3..e8ce4f336caa 100644 --- a/services/core/java/com/android/server/vibrator/DeviceVibrationEffectAdapter.java +++ b/services/core/java/com/android/server/vibrator/DeviceVibrationEffectAdapter.java @@ -16,6 +16,7 @@ package com.android.server.vibrator; +import android.content.Context; import android.os.VibrationEffect; import android.os.VibratorInfo; @@ -26,17 +27,16 @@ import java.util.List; final class DeviceVibrationEffectAdapter implements VibrationEffectAdapters.EffectAdapter<VibratorInfo> { - /** Duration of each step created to simulate a ramp segment. */ - private static final int RAMP_STEP_DURATION_MILLIS = 5; - private final List<VibrationEffectAdapters.SegmentsAdapter<VibratorInfo>> mSegmentAdapters; - DeviceVibrationEffectAdapter() { + DeviceVibrationEffectAdapter(Context context) { mSegmentAdapters = Arrays.asList( // TODO(b/167947076): add filter that removes unsupported primitives // TODO(b/167947076): add filter that replaces unsupported prebaked with fallback - new RampToStepAdapter(RAMP_STEP_DURATION_MILLIS), - new StepToRampAdapter(), + new RampToStepAdapter(context.getResources().getInteger( + com.android.internal.R.integer.config_vibrationWaveformRampStepDuration)), + new StepToRampAdapter(context.getResources().getInteger( + com.android.internal.R.integer.config_vibrationWaveformRampDownDuration)), new ClippingAmplitudeAndFrequencyAdapter() ); } diff --git a/services/core/java/com/android/server/vibrator/RampToStepAdapter.java b/services/core/java/com/android/server/vibrator/RampToStepAdapter.java index 1e05bdbdf082..64624a28c5da 100644 --- a/services/core/java/com/android/server/vibrator/RampToStepAdapter.java +++ b/services/core/java/com/android/server/vibrator/RampToStepAdapter.java @@ -29,7 +29,7 @@ import java.util.List; /** * Adapter that converts ramp segments that to a sequence of fixed step segments. * - * <p>This leaves the list unchanged if the device have compose PWLE capability. + * <p>This leaves the list unchanged if the device has compose PWLE capability. */ final class RampToStepAdapter implements VibrationEffectAdapters.SegmentsAdapter<VibratorInfo> { diff --git a/services/core/java/com/android/server/vibrator/StepToRampAdapter.java b/services/core/java/com/android/server/vibrator/StepToRampAdapter.java index f78df9208fbd..d439b94ec2fc 100644 --- a/services/core/java/com/android/server/vibrator/StepToRampAdapter.java +++ b/services/core/java/com/android/server/vibrator/StepToRampAdapter.java @@ -27,39 +27,221 @@ import java.util.List; /** * Adapter that converts step segments that should be handled as PWLEs to ramp segments. * - * <p>This leaves the list unchanged if the device do not have compose PWLE capability. + * <p>Each replaced {@link StepSegment} will be represented by a {@link RampSegment} with same + * start and end amplitudes/frequencies, which can then be converted to PWLE compositions. This + * adapter leaves the segments unchanged if the device doesn't have the PWLE composition capability. + * + * <p>This adapter also applies the ramp down duration config on devices with PWLE support. This + * prevents the device from ringing when it cannot handle abrupt changes between ON and OFF states. + * This will not change other types of abrupt amplitude changes in the original effect. + * + * <p>The effect overall duration is preserved by this transformation. Waveforms with ON/OFF + * segments are handled gracefully by the ramp down changes. Each OFF segment preceded by an ON + * segment will be shortened, and a ramp down will be added to the transition between ON and OFF. + * The ramps can be shorter than the configured duration in order to preserve the waveform timings, + * but they will still soften the ringing effect. */ final class StepToRampAdapter implements VibrationEffectAdapters.SegmentsAdapter<VibratorInfo> { + + private final int mRampDownDuration; + + StepToRampAdapter(int rampDownDuration) { + mRampDownDuration = rampDownDuration; + } + @Override public int apply(List<VibrationEffectSegment> segments, int repeatIndex, VibratorInfo info) { if (!info.hasCapability(IVibrator.CAP_COMPOSE_PWLE_EFFECTS)) { - // The vibrator do not have PWLE capability, so keep the segments unchanged. + // The vibrator does not have PWLE capability, so keep the segments unchanged. return repeatIndex; } + convertStepsToRamps(segments); + int newRepeatIndex = addRampDownToZeroAmplitudeSegments(segments, repeatIndex); + newRepeatIndex = addRampDownToLoop(segments, newRepeatIndex); + return newRepeatIndex; + } + + private void convertStepsToRamps(List<VibrationEffectSegment> segments) { int segmentCount = segments.size(); + if (mRampDownDuration > 0) { + // Convert all steps to ramps if the device requires ramp down. + for (int i = 0; i < segmentCount; i++) { + if (isStep(segments.get(i))) { + segments.set(i, apply((StepSegment) segments.get(i))); + } + } + return; + } // Convert steps that require frequency control to ramps. for (int i = 0; i < segmentCount; i++) { VibrationEffectSegment segment = segments.get(i); - if ((segment instanceof StepSegment) - && ((StepSegment) segment).getFrequency() != 0) { + if (isStep(segment) && ((StepSegment) segment).getFrequency() != 0) { segments.set(i, apply((StepSegment) segment)); } } // Convert steps that are next to ramps to also become ramps, so they can be composed // together in the same PWLE waveform. - for (int i = 1; i < segmentCount; i++) { + for (int i = 0; i < segmentCount; i++) { if (segments.get(i) instanceof RampSegment) { - for (int j = i - 1; j >= 0 && (segments.get(j) instanceof StepSegment); j--) { + for (int j = i - 1; j >= 0 && isStep(segments.get(j)); j--) { segments.set(j, apply((StepSegment) segments.get(j))); } + for (int j = i + 1; j < segmentCount && isStep(segments.get(j)); j++) { + segments.set(j, apply((StepSegment) segments.get(j))); + } + } + } + } + + /** + * This will add a ramp to zero as follows: + * + * <ol> + * <li>Remove the {@link VibrationEffectSegment} that starts and ends at zero amplitude + * and follows a segment that ends at non-zero amplitude; + * <li>Add a ramp down to zero starting at the previous segment end amplitude and frequency, + * with min between the removed segment duration and the configured ramp down duration; + * <li>Add a zero amplitude segment following the ramp with the remaining duration, if + * necessary; + * </ol> + */ + private int addRampDownToZeroAmplitudeSegments(List<VibrationEffectSegment> segments, + int repeatIndex) { + if (mRampDownDuration <= 0) { + // Nothing to do, no ramp down duration configured. + return repeatIndex; + } + int newRepeatIndex = repeatIndex; + int newSegmentCount = segments.size(); + for (int i = 1; i < newSegmentCount; i++) { + if (!isOffRampSegment(segments.get(i)) + || !endsWithNonZeroAmplitude(segments.get(i - 1))) { + continue; + } + + // We know the previous segment is a ramp that ends at non-zero amplitude. + float previousAmplitude = ((RampSegment) segments.get(i - 1)).getEndAmplitude(); + float previousFrequency = ((RampSegment) segments.get(i - 1)).getEndFrequency(); + RampSegment ramp = (RampSegment) segments.get(i); + + if (ramp.getDuration() <= mRampDownDuration) { + // Replace the zero amplitude segment with a ramp down of same duration, to + // preserve waveform timings and still soften the transition to zero. + segments.set(i, createRampDown(previousAmplitude, previousFrequency, + ramp.getDuration())); + } else { + // Make the zero amplitude segment shorter, to preserve waveform timings, and add a + // ramp down to zero segment right before it. + segments.set(i, updateDuration(ramp, ramp.getDuration() - mRampDownDuration)); + segments.add(i, createRampDown(previousAmplitude, previousFrequency, + mRampDownDuration)); + if (repeatIndex > i) { + newRepeatIndex++; + } + i++; + newSegmentCount++; + } + } + return newRepeatIndex; + } + + /** + * This will add a ramp to zero at the repeating index of the given effect, if set, only if + * the last segment ends at a non-zero amplitude and the repeating segment starts and ends at + * zero amplitude. The update is described as: + * + * <ol> + * <li>Add a ramp down to zero following the last segment, with the min between the + * removed segment duration and the configured ramp down duration; + * <li>Skip the zero-amplitude segment by incrementing the repeat index, splitting it if + * necessary to skip the correct amount; + * </ol> + */ + private int addRampDownToLoop(List<VibrationEffectSegment> segments, int repeatIndex) { + if (repeatIndex < 0) { + // Non-repeating compositions should remain unchanged so duration will be preserved. + return repeatIndex; + } + + int segmentCount = segments.size(); + if (mRampDownDuration <= 0 || !endsWithNonZeroAmplitude(segments.get(segmentCount - 1))) { + // Nothing to do, no ramp down duration configured or composition already ends at zero. + return repeatIndex; + } + + // We know the last segment is a ramp that ends at non-zero amplitude. + RampSegment lastRamp = (RampSegment) segments.get(segmentCount - 1); + float previousAmplitude = lastRamp.getEndAmplitude(); + float previousFrequency = lastRamp.getEndFrequency(); + + if (isOffRampSegment(segments.get(repeatIndex))) { + // Repeating from a non-zero to a zero amplitude segment, we know the next segment is a + // ramp with zero amplitudes. + RampSegment nextRamp = (RampSegment) segments.get(repeatIndex); + + if (nextRamp.getDuration() <= mRampDownDuration) { + // Skip the zero amplitude segment and append a ramp down of same duration to the + // end of the composition, to preserve waveform timings and still soften the + // transition to zero. + // This will update the waveform as follows: + // R R+1 + // | ____ | ____ + // _|_/ => __|/ \ + segments.add(createRampDown(previousAmplitude, previousFrequency, + nextRamp.getDuration())); + repeatIndex++; + } else { + // Append a ramp down to the end of the composition, split the zero amplitude + // segment and start repeating from the second half, to preserve waveform timings. + // This will update the waveform as follows: + // R R+1 + // | ____ | ____ + // _|__/ => __|_/ \ + segments.add(createRampDown(previousAmplitude, previousFrequency, + mRampDownDuration)); + segments.set(repeatIndex, updateDuration(nextRamp, + nextRamp.getDuration() - mRampDownDuration)); + segments.add(repeatIndex, updateDuration(nextRamp, mRampDownDuration)); + repeatIndex++; } } + return repeatIndex; } - private RampSegment apply(StepSegment segment) { + private static RampSegment apply(StepSegment segment) { return new RampSegment(segment.getAmplitude(), segment.getAmplitude(), segment.getFrequency(), segment.getFrequency(), (int) segment.getDuration()); } + + private static RampSegment createRampDown(float amplitude, float frequency, long duration) { + return new RampSegment(amplitude, /* endAmplitude= */ 0, frequency, frequency, + (int) duration); + } + + private static RampSegment updateDuration(RampSegment ramp, long newDuration) { + return new RampSegment(ramp.getStartAmplitude(), ramp.getEndAmplitude(), + ramp.getStartFrequency(), ramp.getEndFrequency(), (int) newDuration); + } + + private static boolean isStep(VibrationEffectSegment segment) { + return segment instanceof StepSegment; + } + + /** Returns true if the segment is a ramp that starts and ends at zero amplitude. */ + private static boolean isOffRampSegment(VibrationEffectSegment segment) { + if (segment instanceof RampSegment) { + RampSegment ramp = (RampSegment) segment; + return ramp.getStartAmplitude() == 0 && ramp.getEndAmplitude() == 0; + } + return false; + } + + private static boolean endsWithNonZeroAmplitude(VibrationEffectSegment segment) { + if (segment instanceof RampSegment) { + return ((RampSegment) segment).getEndAmplitude() != 0; + } + return false; + } } diff --git a/services/core/java/com/android/server/vibrator/VibrationThread.java b/services/core/java/com/android/server/vibrator/VibrationThread.java index e3672f4d497c..150fde99b706 100644 --- a/services/core/java/com/android/server/vibrator/VibrationThread.java +++ b/services/core/java/com/android/server/vibrator/VibrationThread.java @@ -95,8 +95,7 @@ final class VibrationThread extends Thread implements IBinder.DeathRecipient { private final WorkSource mWorkSource = new WorkSource(); private final PowerManager.WakeLock mWakeLock; private final IBatteryStats mBatteryStatsService; - private final DeviceVibrationEffectAdapter mDeviceEffectAdapter = - new DeviceVibrationEffectAdapter(); + private final DeviceVibrationEffectAdapter mDeviceEffectAdapter; private final Vibration mVibration; private final VibrationCallbacks mCallbacks; private final SparseArray<VibratorController> mVibrators = new SparseArray<>(); @@ -104,10 +103,11 @@ final class VibrationThread extends Thread implements IBinder.DeathRecipient { private volatile boolean mForceStop; - VibrationThread(Vibration vib, SparseArray<VibratorController> availableVibrators, - PowerManager.WakeLock wakeLock, IBatteryStats batteryStatsService, - VibrationCallbacks callbacks) { + VibrationThread(Vibration vib, DeviceVibrationEffectAdapter effectAdapter, + SparseArray<VibratorController> availableVibrators, PowerManager.WakeLock wakeLock, + IBatteryStats batteryStatsService, VibrationCallbacks callbacks) { mVibration = vib; + mDeviceEffectAdapter = effectAdapter; mCallbacks = callbacks; mWakeLock = wakeLock; mWorkSource.set(vib.uid); diff --git a/services/core/java/com/android/server/vibrator/VibratorManagerService.java b/services/core/java/com/android/server/vibrator/VibratorManagerService.java index 06a5077bec82..2f0ed19d867a 100644 --- a/services/core/java/com/android/server/vibrator/VibratorManagerService.java +++ b/services/core/java/com/android/server/vibrator/VibratorManagerService.java @@ -132,6 +132,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { private final VibrationSettings mVibrationSettings; private final VibrationScaler mVibrationScaler; private final InputDeviceDelegate mInputDeviceDelegate; + private final DeviceVibrationEffectAdapter mDeviceVibrationEffectAdapter; private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { @Override @@ -175,6 +176,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { mVibrationSettings = new VibrationSettings(mContext, mHandler); mVibrationScaler = new VibrationScaler(mContext, mVibrationSettings); mInputDeviceDelegate = new InputDeviceDelegate(mContext, mHandler); + mDeviceVibrationEffectAdapter = new DeviceVibrationEffectAdapter(mContext); VibrationCompleteListener listener = new VibrationCompleteListener(this); mNativeWrapper = injector.getNativeWrapper(); @@ -512,8 +514,8 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { return Vibration.Status.FORWARDED_TO_INPUT_DEVICES; } - VibrationThread vibThread = new VibrationThread(vib, mVibrators, mWakeLock, - mBatteryStatsService, mVibrationCallbacks); + VibrationThread vibThread = new VibrationThread(vib, mDeviceVibrationEffectAdapter, + mVibrators, mWakeLock, mBatteryStatsService, mVibrationCallbacks); if (mCurrentVibration == null) { return startVibrationThreadLocked(vibThread); diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java index c888e545b24e..53f1035ee422 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 @@ public class WallpaperManagerService extends IWallpaperManager.Stub } // 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 @@ public class WallpaperManagerService extends IWallpaperManager.Stub 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 2b6a83896cc6..14f6fb3ed99a 100644 --- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java +++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java @@ -312,6 +312,12 @@ class ActivityMetricsLogger { } } + /** Returns {@code true} if the incoming activity can belong to this transition. */ + boolean canCoalesce(ActivityRecord r) { + return mLastLaunchedActivity.mDisplayContent == r.mDisplayContent + && mLastLaunchedActivity.getWindowingMode() == r.getWindowingMode(); + } + /** @return {@code true} if the activity matches a launched activity in this transition. */ boolean contains(ActivityRecord r) { return r != null && (r == mLastLaunchedActivity || mPendingDrawActivities.contains(r)); @@ -604,8 +610,7 @@ class ActivityMetricsLogger { return; } - final DisplayContent targetDisplay = launchedActivity.mDisplayContent; - if (info != null && info.mLastLaunchedActivity.mDisplayContent == targetDisplay) { + if (info != null && info.canCoalesce(launchedActivity)) { // If we are already in an existing transition on the same display, only update the // activity name, but not the other attributes. @@ -633,7 +638,7 @@ class ActivityMetricsLogger { // As abort for no process switch. launchObserverNotifyIntentFailed(); } - if (targetDisplay.isSleeping()) { + if (launchedActivity.mDisplayContent.isSleeping()) { // It is unknown whether the activity can be drawn or not, e.g. ut depends on the // keyguard states and the attributes or flags set by the activity. If the activity // keeps invisible in the grace period, the tracker will be cancelled so it won't get diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 660cd37b123c..8cc6a42be349 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -309,6 +309,7 @@ import android.view.animation.Animation; import android.window.IRemoteTransition; import android.window.SizeConfigurationBuckets; import android.window.SplashScreen; +import android.window.SplashScreenView; import android.window.SplashScreenView.SplashScreenViewParcelable; import android.window.TaskSnapshot; import android.window.WindowContainerToken; @@ -716,25 +717,29 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A boolean startingMoved; boolean mHandleExitSplashScreen; - @TransferSplashScreenState int mTransferringSplashScreenState = - TRANSFER_SPLASH_SCREEN_IDLE; + @TransferSplashScreenState + int mTransferringSplashScreenState = TRANSFER_SPLASH_SCREEN_IDLE; - // Idle, can be triggered to do transfer if needed. + /** Idle, can be triggered to do transfer if needed. */ static final int TRANSFER_SPLASH_SCREEN_IDLE = 0; - // requesting a copy from shell. + + /** Requesting a copy from shell. */ static final int TRANSFER_SPLASH_SCREEN_COPYING = 1; - // attach the splash screen view to activity. + + /** Attach the splash screen view to activity. */ static final int TRANSFER_SPLASH_SCREEN_ATTACH_TO_CLIENT = 2; - // client has taken over splash screen view. + + /** Client has taken over splash screen view. */ static final int TRANSFER_SPLASH_SCREEN_FINISH = 3; - @IntDef(prefix = { "TRANSFER_SPLASH_SCREEN_" }, value = { + @IntDef(prefix = {"TRANSFER_SPLASH_SCREEN_"}, value = { TRANSFER_SPLASH_SCREEN_IDLE, TRANSFER_SPLASH_SCREEN_COPYING, TRANSFER_SPLASH_SCREEN_ATTACH_TO_CLIENT, TRANSFER_SPLASH_SCREEN_FINISH, }) - @interface TransferSplashScreenState {} + @interface TransferSplashScreenState { + } // How long we wait until giving up transfer splash screen. private static final int TRANSFER_SPLASH_SCREEN_TIMEOUT = 2000; @@ -2196,6 +2201,23 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A removeStartingWindowAnimation(false /* prepareAnimation */); } + /** + * Notify the shell ({@link com.android.wm.shell.ShellTaskOrganizer} it should clean up any + * remaining reference to this {@link ActivityRecord}'s splash screen. + * @see com.android.wm.shell.ShellTaskOrganizer#onAppSplashScreenViewRemoved(int) + * @see SplashScreenView#remove() + */ + void cleanUpSplashScreen() { + // We only clean up the splash screen if we were supposed to handle it. If it was + // transferred to another activity, the next one will handle the clean up. + if (mHandleExitSplashScreen && !startingMoved + && (mTransferringSplashScreenState == TRANSFER_SPLASH_SCREEN_FINISH + || mTransferringSplashScreenState == TRANSFER_SPLASH_SCREEN_IDLE)) { + ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Cleaning splash screen token=%s", this); + mAtmService.mTaskOrganizerController.onAppSplashScreenViewRemoved(getTask()); + } + } + void removeStartingWindow() { removeStartingWindowAnimation(true /* prepareAnimation */); } @@ -3343,6 +3365,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A task.cleanUpActivityReferences(this); clearLastParentBeforePip(); + // Clean up the splash screen if it was still displayed. + cleanUpSplashScreen(); + deferRelaunchUntilPaused = false; frozenBeforeDestroy = false; @@ -8086,6 +8111,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A 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 e7c51a4ac65a..4acadb21b5e3 100644 --- a/services/core/java/com/android/server/wm/AppTransitionController.java +++ b/services/core/java/com/android/server/wm/AppTransitionController.java @@ -623,7 +623,11 @@ public class AppTransitionController { siblings.add(current); boolean canPromote = true; - if (parent == null || !parent.canCreateRemoteAnimationTarget()) { + if (parent == null || !parent.canCreateRemoteAnimationTarget() + // We cannot promote the animation on Task's parent when the task is in + // clearing task in case the animating get stuck when performing the opening + // task that behind it. + || (current.asTask() != null && current.asTask().mInRemoveTask)) { canPromote = false; } else { // In case a descendant of the parent belongs to the other group, we cannot promote @@ -800,7 +804,8 @@ public class AppTransitionController { } 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 +817,9 @@ public class AppTransitionController { } } } - 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/Task.java b/services/core/java/com/android/server/wm/Task.java index 82d1c04591a6..565f99f80890 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -6689,24 +6689,26 @@ class Task extends WindowContainer<WindowContainer> { } } - // TODO(185200798): Persist theme name instead of theme if - int splashScreenThemeResId = options != null - ? options.getSplashScreenThemeResId() : 0; - - // User can override the splashscreen theme. The theme name is used to persist - // the setting, so if no theme is set in the ActivityOptions, we check if has - // been persisted here. - if (splashScreenThemeResId == 0) { + // Find the splash screen theme. User can override the persisted theme by + // ActivityOptions. + String splashScreenThemeResName = options != null + ? options.getSplashScreenThemeResName() : null; + if (splashScreenThemeResName == null || splashScreenThemeResName.isEmpty()) { try { - String themeName = mAtmService.getPackageManager() + splashScreenThemeResName = mAtmService.getPackageManager() .getSplashScreenTheme(r.packageName, r.mUserId); - if (themeName != null) { - Context packageContext = mAtmService.mContext - .createPackageContext(r.packageName, 0); - splashScreenThemeResId = packageContext.getResources() - .getIdentifier(themeName, null, null); - } - } catch (RemoteException | PackageManager.NameNotFoundException + } catch (RemoteException ignore) { + // Just use the default theme + } + } + int splashScreenThemeResId = 0; + if (splashScreenThemeResName != null && !splashScreenThemeResName.isEmpty()) { + try { + final Context packageContext = mAtmService.mContext + .createPackageContext(r.packageName, 0); + splashScreenThemeResId = packageContext.getResources() + .getIdentifier(splashScreenThemeResName, null, null); + } catch (PackageManager.NameNotFoundException | Resources.NotFoundException ignore) { // Just use the default theme } @@ -7653,17 +7655,23 @@ class Task extends WindowContainer<WindowContainer> { 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/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java index f23028f6f67a..3a2ca80f2e12 100644 --- a/services/core/java/com/android/server/wm/TaskOrganizerController.java +++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java @@ -43,6 +43,7 @@ import android.util.proto.ProtoOutputStream; import android.view.SurfaceControl; import android.window.ITaskOrganizer; import android.window.ITaskOrganizerController; +import android.window.SplashScreenView; import android.window.StartingWindowInfo; import android.window.TaskAppearedInfo; import android.window.TaskSnapshot; @@ -215,6 +216,14 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub { } } + void onAppSplashScreenViewRemoved(Task task) { + try { + mTaskOrganizer.onAppSplashScreenViewRemoved(task.mTaskId); + } catch (RemoteException e) { + Slog.e(TAG, "Exception sending onAppSplashScreenViewRemoved callback", e); + } + } + SurfaceControl prepareLeash(Task task, String reason) { return new SurfaceControl(task.getSurfaceControl(), reason); } @@ -314,6 +323,10 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub { mOrganizer.copySplashScreenView(t); } + public void onAppSplashScreenViewRemoved(Task t) { + mOrganizer.onAppSplashScreenViewRemoved(t); + } + /** * Register this task with this state, but doesn't trigger the task appeared callback to * the organizer. @@ -566,6 +579,22 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub { return true; } + /** + * Notify the shell ({@link com.android.wm.shell.ShellTaskOrganizer} that the client has + * removed the splash screen view. + * @see com.android.wm.shell.ShellTaskOrganizer#onAppSplashScreenViewRemoved(int) + * @see SplashScreenView#remove() + */ + public void onAppSplashScreenViewRemoved(Task task) { + final Task rootTask = task.getRootTask(); + if (rootTask == null || rootTask.mTaskOrganizer == null) { + return; + } + final TaskOrganizerState state = + mTaskOrganizerStates.get(rootTask.mTaskOrganizer.asBinder()); + state.onAppSplashScreenViewRemoved(task); + } + void onTaskAppeared(ITaskOrganizer organizer, Task task) { final TaskOrganizerState state = mTaskOrganizerStates.get(organizer.asBinder()); if (state != null && state.addTask(task)) { diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java index 42e2d2fc79d3..0cd098070401 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 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe 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/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 1042a0b13e1c..6d51849ea513 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 @@ public class WindowManagerService extends IWindowManager.Stub 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 @@ public class WindowManagerService extends IWindowManager.Stub + " 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 642ce1b34769..1a468d9f4ee9 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.ACTIVITY_TYPE_HOME; 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; @@ -60,6 +61,7 @@ import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_M import static android.view.WindowManager.LayoutParams.MATCH_PARENT; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME; +import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NOT_MAGNIFIABLE; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_WILL_NOT_REPLACE_ON_RELAUNCH; @@ -3928,7 +3930,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP 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); } @@ -3944,7 +3948,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP 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); } @@ -5380,6 +5386,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP || mAttrs.type == TYPE_NAVIGATION_BAR_PANEL) { return false; } + if ((mAttrs.privateFlags & PRIVATE_FLAG_NOT_MAGNIFIABLE) != 0) { + return false; + } return true; } @@ -5444,12 +5453,18 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP 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); + } } } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 228bc0ecc051..fa24e5238820 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.Manifest.permission.REQUEST_PASSWORD_COMPLEXITY; 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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { 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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { 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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { 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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { 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"); @@ -6748,7 +6832,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public void wipeDataWithReason(int flags, String wipeReasonForUser, boolean calledOnParentInstance) { - if (!mHasFeature) { + if (!mHasFeature && !hasCallingOrSelfPermission(permission.MASTER_CLEAR)) { return; } final CallerIdentity caller = getCallerIdentity(); @@ -8390,12 +8474,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { 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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { 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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { 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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { 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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { + " 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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { 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( @@ -17462,14 +17550,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @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 280f12f6a60e..685cf0580a48 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 @@ package com.android.server.devicepolicy; 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 android.view.inputmethod.InputMethodInfo; 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 @@ import java.util.Set; 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 @@ public class OverlayPackagesProvider { 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 class OverlayPackagesProvider { 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 @@ public class OverlayPackagesProvider { /** * 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 @@ public class OverlayPackagesProvider { @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 48d2d73543fb..532823ad8367 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 @@ package com.android.server.devicepolicy; 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 @@ public final class PersonalAppsSuspensionHelper { } 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 @@ public final class PersonalAppsSuspensionHelper { 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/incremental/IncrementalService.cpp b/services/incremental/IncrementalService.cpp index 47d59b250e29..757c9dec06ed 100644 --- a/services/incremental/IncrementalService.cpp +++ b/services/incremental/IncrementalService.cpp @@ -89,6 +89,11 @@ struct Constants { // 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 @@ void IncrementalService::DataLoaderStub::cleanupResources() { 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 @@ bool IncrementalService::DataLoaderStub::fsmStep() { 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 @@ bool IncrementalService::DataLoaderStub::fsmStep() { 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 @@ binder::Status IncrementalService::DataLoaderStub::onStatusChanged(MountId mount } 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 @@ void IncrementalService::DataLoaderStub::setCurrentStatus(int newStatus) { 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 5de7325b3d28..b81e1b1b071c 100644 --- a/services/incremental/IncrementalService.h +++ b/services/incremental/IncrementalService.h @@ -255,6 +255,7 @@ private: 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 094c5fb36eea..59d96d2393ef 100644 --- a/services/incremental/test/IncrementalServiceTest.cpp +++ b/services/incremental/test/IncrementalServiceTest.cpp @@ -808,7 +808,9 @@ public: 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 d55d0600b7c9..ef1201e16ba0 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 @@ public class DataManager { 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 @@ public class DataManager { 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 @@ public class DataManager { 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 @@ public class DataManager { 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 @@ public class DataManager { } @VisibleForTesting - NotificationListenerService getNotificationListenerServiceForTesting(@UserIdInt int userId) { + NotificationListener getNotificationListenerServiceForTesting(@UserIdInt int userId) { return mNotificationListeners.get(userId); } @@ -1132,7 +1144,7 @@ public class DataManager { } @Override - public void onNotificationPosted(StatusBarNotification sbn) { + public void onNotificationPosted(StatusBarNotification sbn, RankingMap map) { if (sbn.getUser().getIdentifier() != mUserId) { return; } @@ -1145,16 +1157,22 @@ public class DataManager { }); 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 6c5c1d4b59eb..b4f8b6edd139 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 android.util.ArrayMap 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.android.server.wm.ActivityTaskManagerInternal 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 @@ class PackageManagerComponentLabelIconOverrideTest { 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 @@ class PackageManagerComponentLabelIconOverrideTest { // 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 @@ class PackageManagerComponentLabelIconOverrideTest { } } + @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 @@ class PackageManagerComponentLabelIconOverrideTest { 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 @@ class PackageManagerComponentLabelIconOverrideTest { 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 @@ class PackageManagerComponentLabelIconOverrideTest { } } 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 24e11af23798..ff7cd75dd7a1 100644 --- a/services/tests/mockingservicestests/Android.bp +++ b/services/tests/mockingservicestests/Android.bp @@ -45,6 +45,7 @@ android_test { "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 f01120e1ed4c..5a6275d71d1e 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 com.google.common.truth.Truth.assertWithMessage; 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 @@ public final class MasterClearReceiverTest { @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 @@ public final class MasterClearReceiverTest { 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 @@ public final class MasterClearReceiverTest { 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 @@ public final class MasterClearReceiverTest { }).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 @@ public final class MasterClearReceiverTest { 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 @@ public final class MasterClearReceiverTest { 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 d5e1cd6e0415..21de7916e23d 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.Alarm.EXACT_ALLOW_REASON_PERMISSION; 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.argThat; 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.AppStateTrackerImpl; 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 org.mockito.stubbing.Answer; 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 @@ public class AlarmManagerServiceTest { .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 @@ public class AlarmManagerServiceTest { 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 @@ public class AlarmManagerServiceTest { 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 @@ public class AlarmManagerServiceTest { @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 @@ public class AlarmManagerServiceTest { @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 @@ public class AlarmManagerServiceTest { } @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 @@ public class AlarmManagerServiceTest { @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 @@ public class AlarmManagerServiceTest { @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 @@ public class AlarmManagerServiceTest { @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 @@ public class AlarmManagerServiceTest { @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 @@ public class AlarmManagerServiceTest { @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 @@ public class AlarmManagerServiceTest { @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 @@ public class AlarmManagerServiceTest { } 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 @@ public class AlarmManagerServiceTest { @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 @@ public class AlarmManagerServiceTest { @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 @@ public class AlarmManagerServiceTest { @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 @@ public class AlarmManagerServiceTest { @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 @@ public class AlarmManagerServiceTest { @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 @@ public class AlarmManagerServiceTest { @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 class AlarmManagerServiceTest { 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 @@ public class AlarmManagerServiceTest { @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 @@ public class AlarmManagerServiceTest { @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 @@ public class AlarmManagerServiceTest { @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 @@ public class AlarmManagerServiceTest { @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 @@ public class AlarmManagerServiceTest { } @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 @@ public class AlarmManagerServiceTest { } @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 @@ public class AlarmManagerServiceTest { @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 @@ public class AlarmManagerServiceTest { // 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 @@ public class AlarmManagerServiceTest { } @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 000000000000..da0b83ec819c --- /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/mockingservicestests/src/com/android/server/location/provider/MockableLocationProviderTest.java b/services/tests/mockingservicestests/src/com/android/server/location/provider/MockableLocationProviderTest.java index cf5db2e0db98..8532dbb7f38a 100644 --- a/services/tests/mockingservicestests/src/com/android/server/location/provider/MockableLocationProviderTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/location/provider/MockableLocationProviderTest.java @@ -158,7 +158,7 @@ public class MockableLocationProviderTest { @Test public void testSetState() { - assertThat(mProvider.isAllowed()).isFalse(); + assertThat(mProvider.getState().allowed).isFalse(); AbstractLocationProvider.State newState; diff --git a/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java b/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java index 1ac4a8ed96d0..a71b481372d8 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java @@ -19,6 +19,7 @@ package com.android.server.accessibility; import static android.view.MotionEvent.ACTION_DOWN; import static android.view.MotionEvent.ACTION_HOVER_MOVE; import static android.view.MotionEvent.ACTION_UP; +import static android.view.WindowManagerPolicyConstants.FLAG_INJECTED_FROM_ACCESSIBILITY; import static android.view.WindowManagerPolicyConstants.FLAG_PASS_TO_USER; import static org.hamcrest.CoreMatchers.allOf; @@ -186,9 +187,9 @@ public class MotionEventInjectorTest { verifyNoMoreInteractions(next); mMessageCapturingHandler.sendOneMessage(); // Send a motion event - verify(next).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), eq(FLAG_PASS_TO_USER)); - verify(next).onMotionEvent(argThat(mIsLineStart), argThat(mIsLineStart), - eq(FLAG_PASS_TO_USER)); + final int expectedFlags = FLAG_PASS_TO_USER | FLAG_INJECTED_FROM_ACCESSIBILITY; + verify(next).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), eq(expectedFlags)); + verify(next).onMotionEvent(argThat(mIsLineStart), argThat(mIsLineStart), eq(expectedFlags)); verifyNoMoreInteractions(next); reset(next); @@ -196,7 +197,7 @@ public class MotionEventInjectorTest { mMessageCapturingHandler.sendOneMessage(); // Send a motion event verify(next).onMotionEvent(argThat(allOf(mIsLineMiddle, hasRightDownTime)), - argThat(allOf(mIsLineMiddle, hasRightDownTime)), eq(FLAG_PASS_TO_USER)); + argThat(allOf(mIsLineMiddle, hasRightDownTime)), eq(expectedFlags)); verifyNoMoreInteractions(next); reset(next); @@ -204,7 +205,7 @@ public class MotionEventInjectorTest { mMessageCapturingHandler.sendOneMessage(); // Send a motion event verify(next).onMotionEvent(argThat(allOf(mIsLineEnd, hasRightDownTime)), - argThat(allOf(mIsLineEnd, hasRightDownTime)), eq(FLAG_PASS_TO_USER)); + argThat(allOf(mIsLineEnd, hasRightDownTime)), eq(expectedFlags)); verifyNoMoreInteractions(next); verify(mServiceInterface).onPerformGestureResult(LINE_SEQUENCE, true); @@ -242,7 +243,8 @@ public class MotionEventInjectorTest { mMessageCapturingHandler.sendAllMessages(); // Send all motion events reset(next); mMotionEventInjector.onMotionEvent(mClickDownEvent, mClickDownEvent, 0); - verify(next).onMotionEvent(argThat(mIsClickDown), argThat(mIsClickDown), eq(0)); + verify(next).onMotionEvent(argThat(mIsClickDown), argThat(mIsClickDown), + eq(FLAG_INJECTED_FROM_ACCESSIBILITY)); } @Test @@ -258,7 +260,8 @@ public class MotionEventInjectorTest { mMessageCapturingHandler.sendOneMessage(); // Send a motion event verify(next).onMotionEvent( - argThat(mIsLineStart), argThat(mIsLineStart), eq(FLAG_PASS_TO_USER)); + argThat(mIsLineStart), argThat(mIsLineStart), + eq(FLAG_PASS_TO_USER | FLAG_INJECTED_FROM_ACCESSIBILITY)); } @Test @@ -289,9 +292,11 @@ public class MotionEventInjectorTest { reset(next); mMessageCapturingHandler.sendOneMessage(); // Send a motion event - verify(next).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), eq(FLAG_PASS_TO_USER)); + verify(next).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), + eq(FLAG_PASS_TO_USER | FLAG_INJECTED_FROM_ACCESSIBILITY)); verify(next).onMotionEvent( - argThat(mIsLineStart), argThat(mIsLineStart), eq(FLAG_PASS_TO_USER)); + argThat(mIsLineStart), argThat(mIsLineStart), + eq(FLAG_PASS_TO_USER | FLAG_INJECTED_FROM_ACCESSIBILITY)); } @Test 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 eace99f61e60..e19aa727b735 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.InstrumentationRegistry; 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 @@ import java.util.regex.Pattern; 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 @@ public class ActivityManagerTest { 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 @@ public class ActivityManagerTest { // 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 class ActivityManagerTest { 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 @@ public class ActivityManagerTest { 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 @@ public class ActivityManagerTest { 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 @@ public class ActivityManagerTest { 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 @@ public class ActivityManagerTest { } 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 @@ public class ActivityManagerTest { 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 @@ public class ActivityManagerTest { 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 @@ public class ActivityManagerTest { 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 @@ public class ActivityManagerTest { 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 @@ public class ActivityManagerTest { // 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 @@ public class ActivityManagerTest { 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 @@ public class ActivityManagerTest { } } + @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 3bcbcbdbd2c8..8666fa6ac35a 100644 --- a/services/tests/servicestests/src/com/android/server/appsearch/AppSearchImplPlatformTest.java +++ b/services/tests/servicestests/src/com/android/server/appsearch/AppSearchImplPlatformTest.java @@ -57,6 +57,11 @@ import java.util.Map; /** This tests AppSearchImpl when it's running with a platform-backed VisibilityStore. */ public class AppSearchImplPlatformTest { + /** + * Always trigger optimize in this class. OptimizeStrategy will be tested in its own test class. + */ + private static final OptimizeStrategy ALWAYS_OPTIMIZE = optimizeInfo -> true; + @Rule public TemporaryFolder mTemporaryFolder = new TemporaryFolder(); private final Map<UserHandle, PackageManager> mMockPackageManagers = new ArrayMap<>(); private Context mContext; @@ -88,7 +93,8 @@ public class AppSearchImplPlatformTest { AppSearchImpl.create( mTemporaryFolder.newFolder(), mContext, - /*logger=*/ null); + /*logger=*/ null, + ALWAYS_OPTIMIZE); mGlobalQuerierUid = mContext.getPackageManager().getPackageUid(mContext.getPackageName(), /*flags=*/ 0); 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 6ac4d138c9d1..4faffc025e2f 100644 --- a/services/tests/servicestests/src/com/android/server/appsearch/VisibilityStoreTest.java +++ b/services/tests/servicestests/src/com/android/server/appsearch/VisibilityStoreTest.java @@ -56,6 +56,11 @@ import java.util.Collections; import java.util.Map; public class VisibilityStoreTest { + /** + * Always trigger optimize in this class. OptimizeStrategy will be tested in its own test class. + */ + private static final OptimizeStrategy ALWAYS_OPTIMIZE = optimizeInfo -> true; + @Rule public TemporaryFolder mTemporaryFolder = new TemporaryFolder(); private final Map<UserHandle, PackageManager> mMockPackageManagers = new ArrayMap<>(); private Context mContext; @@ -87,7 +92,8 @@ public class VisibilityStoreTest { AppSearchImpl.create( mTemporaryFolder.newFolder(), mContext, - /*logger=*/ null); + /*logger=*/ null, + ALWAYS_OPTIMIZE); mUid = mContext.getPackageManager().getPackageUid(mContext.getPackageName(), /*flags=*/ 0); mVisibilityStore = appSearchImpl.getVisibilityStoreLocked(); 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 5a8c44caa0a3..e26cfeab1529 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 @@ -76,17 +76,22 @@ import java.util.Set; public class AppSearchImplTest { @Rule public TemporaryFolder mTemporaryFolder = new TemporaryFolder(); private AppSearchImpl mAppSearchImpl; + /** + * Always trigger optimize in this class. OptimizeStrategy will be tested in its own test class. + */ + private static final OptimizeStrategy ALWAYS_OPTIMIZE = optimizeInfo -> true; @Before public void setUp() throws Exception { Context context = ApplicationProvider.getApplicationContext(); - // Give ourselves global query permissions + // Give ourselves global query permissions. mAppSearchImpl = AppSearchImpl.create( mTemporaryFolder.newFolder(), context, - /*logger=*/ null); + /*logger=*/ null, + ALWAYS_OPTIMIZE); } /** @@ -423,7 +428,7 @@ public class AppSearchImplTest { } @Test - public void testOptimize() throws Exception { + public void testTriggerCheckOptimizeByMutationSize() throws Exception { // Insert schema List<AppSearchSchema> schemas = Collections.singletonList(new AppSearchSchema.Builder("type").build()); @@ -436,56 +441,30 @@ public class AppSearchImplTest { /*forceOverride=*/ false, /*version=*/ 0); - // Insert enough documents. - for (int i = 0; - i - < AppSearchImpl.OPTIMIZE_THRESHOLD_DOC_COUNT - + AppSearchImpl.CHECK_OPTIMIZE_INTERVAL; - i++) { - GenericDocument document = - new GenericDocument.Builder<>("namespace", "id" + i, "type").build(); - mAppSearchImpl.putDocument("package", "database", document, /*logger=*/ null); - } + // Insert a document and then remove it to generate garbage. + GenericDocument document = new GenericDocument.Builder<>("namespace", "id", "type").build(); + mAppSearchImpl.putDocument("package", "database", document, /*logger=*/ null); + mAppSearchImpl.remove( + "package", "database", "namespace", "id", /*removeStatsBuilder=*/ null); - // Check optimize() will release 0 docs since there is no deletion. + // Verify there is garbage documents. GetOptimizeInfoResultProto optimizeInfo = mAppSearchImpl.getOptimizeInfoResultLocked(); - assertThat(optimizeInfo.getOptimizableDocs()).isEqualTo(0); - - // delete 999 documents, we will reach the threshold to trigger optimize() in next - // deletion. - for (int i = 0; i < AppSearchImpl.OPTIMIZE_THRESHOLD_DOC_COUNT - 1; i++) { - mAppSearchImpl.remove( - "package", "database", "namespace", "id" + i, /*removeStatsBuilder=*/ null); - } + assertThat(optimizeInfo.getOptimizableDocs()).isEqualTo(1); - // Updates the check for optimize counter, checkForOptimize() will be triggered since - // CHECK_OPTIMIZE_INTERVAL is reached but optimize() won't since - // OPTIMIZE_THRESHOLD_DOC_COUNT is not. - mAppSearchImpl.checkForOptimize( - /*mutateBatchSize=*/ AppSearchImpl.OPTIMIZE_THRESHOLD_DOC_COUNT - 1); + // Increase mutation counter and stop before reach the threshold + mAppSearchImpl.checkForOptimize(AppSearchImpl.CHECK_OPTIMIZE_INTERVAL - 1); - // Verify optimize() still not be triggered. + // Verify the optimize() isn't triggered. optimizeInfo = mAppSearchImpl.getOptimizeInfoResultLocked(); - assertThat(optimizeInfo.getOptimizableDocs()) - .isEqualTo(AppSearchImpl.OPTIMIZE_THRESHOLD_DOC_COUNT - 1); - - // Keep delete docs - for (int i = AppSearchImpl.OPTIMIZE_THRESHOLD_DOC_COUNT; - i - < AppSearchImpl.OPTIMIZE_THRESHOLD_DOC_COUNT - + AppSearchImpl.CHECK_OPTIMIZE_INTERVAL; - i++) { - mAppSearchImpl.remove( - "package", "database", "namespace", "id" + i, /*removeStatsBuilder=*/ null); - } - // updates the check for optimize counter, will reach both CHECK_OPTIMIZE_INTERVAL and - // OPTIMIZE_THRESHOLD_DOC_COUNT this time and trigger a optimize(). - mAppSearchImpl.checkForOptimize(/*mutateBatchSize*/ AppSearchImpl.CHECK_OPTIMIZE_INTERVAL); + assertThat(optimizeInfo.getOptimizableDocs()).isEqualTo(1); - // Verify optimize() is triggered + // Increase the counter and reach the threshold, optimize() should be triggered. + mAppSearchImpl.checkForOptimize(/*mutateBatchSize=*/ 1); + + // Verify optimize() is triggered. optimizeInfo = mAppSearchImpl.getOptimizeInfoResultLocked(); - assertThat(optimizeInfo.getOptimizableDocs()) - .isLessThan(AppSearchImpl.CHECK_OPTIMIZE_INTERVAL); + assertThat(optimizeInfo.getOptimizableDocs()).isEqualTo(0); + assertThat(optimizeInfo.getEstimatedOptimizableBytes()).isEqualTo(0); } @Test @@ -493,7 +472,12 @@ public class AppSearchImplTest { // Setup the index Context context = ApplicationProvider.getApplicationContext(); File appsearchDir = mTemporaryFolder.newFolder(); - AppSearchImpl appSearchImpl = AppSearchImpl.create(appsearchDir, context, /*logger=*/ null); + AppSearchImpl appSearchImpl = + AppSearchImpl.create( + appsearchDir, + context, + /*logger=*/ null, + ALWAYS_OPTIMIZE); // Insert schema List<AppSearchSchema> schemas = @@ -522,7 +506,7 @@ public class AppSearchImplTest { /*queryExpression=*/ "", new SearchSpec.Builder().addFilterSchemas("Type1").build(), context.getPackageName(), - VisibilityStore.NO_OP_USER_ID, + VisibilityStore.NO_OP_UID, /*logger=*/ null); assertThat(results.getResults()).hasSize(1); assertThat(results.getResults().get(0).getGenericDocument()).isEqualTo(validDoc); @@ -554,7 +538,9 @@ public class AppSearchImplTest { // Initialize AppSearchImpl. This should cause a reset. appSearchImpl.close(); - appSearchImpl = AppSearchImpl.create(appsearchDir, context, testLogger); + appSearchImpl = + AppSearchImpl.create( + appsearchDir, context, testLogger, ALWAYS_OPTIMIZE); // Check recovery state InitializeStats initStats = testLogger.mInitializeStats; @@ -582,7 +568,7 @@ public class AppSearchImplTest { /*queryExpression=*/ "", new SearchSpec.Builder().addFilterSchemas("Type1").build(), context.getPackageName(), - VisibilityStore.NO_OP_USER_ID, + VisibilityStore.NO_OP_UID, /*logger=*/ null); assertThat(results.getResults()).isEmpty(); @@ -606,7 +592,7 @@ public class AppSearchImplTest { /*queryExpression=*/ "", new SearchSpec.Builder().addFilterSchemas("Type1").build(), context.getPackageName(), - VisibilityStore.NO_OP_USER_ID, + VisibilityStore.NO_OP_UID, /*logger=*/ null); assertThat(results.getResults()).hasSize(1); assertThat(results.getResults().get(0).getGenericDocument()).isEqualTo(validDoc); @@ -862,7 +848,7 @@ public class AppSearchImplTest { "", searchSpec, /*callerPackageName=*/ "", - /*callerUid=*/ 0, + VisibilityStore.NO_OP_UID, /*logger=*/ null); assertThat(searchResultPage.getResults()).isEmpty(); } @@ -1683,7 +1669,8 @@ public class AppSearchImplTest { AppSearchImpl.create( mTemporaryFolder.newFolder(), context, - /*logger=*/ null); + /*logger=*/ null, + ALWAYS_OPTIMIZE); // Initial check that we could do something at first. List<AppSearchSchema> schemas = @@ -1758,7 +1745,7 @@ public class AppSearchImplTest { .setTermMatch(TermMatchType.Code.PREFIX_VALUE) .build(), "package", - /*callerUid=*/ 1, + VisibilityStore.NO_OP_UID, /*logger=*/ null); }); @@ -1830,7 +1817,12 @@ public class AppSearchImplTest { // Setup the index Context context = ApplicationProvider.getApplicationContext(); File appsearchDir = mTemporaryFolder.newFolder(); - AppSearchImpl appSearchImpl = AppSearchImpl.create(appsearchDir, context, /*logger=*/ null); + AppSearchImpl appSearchImpl = + AppSearchImpl.create( + appsearchDir, + context, + /*logger=*/ null, + ALWAYS_OPTIMIZE); List<AppSearchSchema> schemas = Collections.singletonList(new AppSearchSchema.Builder("type").build()); @@ -1856,7 +1848,11 @@ public class AppSearchImplTest { // That document should be visible even from another instance. AppSearchImpl appSearchImpl2 = - AppSearchImpl.create(appsearchDir, context, /*logger=*/ null); + AppSearchImpl.create( + appsearchDir, + context, + /*logger=*/ null, + ALWAYS_OPTIMIZE); getResult = appSearchImpl2.getDocument( "package", "database", "namespace1", "id1", Collections.emptyMap()); @@ -1868,7 +1864,12 @@ public class AppSearchImplTest { // Setup the index Context context = ApplicationProvider.getApplicationContext(); File appsearchDir = mTemporaryFolder.newFolder(); - AppSearchImpl appSearchImpl = AppSearchImpl.create(appsearchDir, context, /*logger=*/ null); + AppSearchImpl appSearchImpl = + AppSearchImpl.create( + appsearchDir, + context, + /*logger=*/ null, + ALWAYS_OPTIMIZE); List<AppSearchSchema> schemas = Collections.singletonList(new AppSearchSchema.Builder("type").build()); @@ -1918,7 +1919,11 @@ public class AppSearchImplTest { // Only the second document should be retrievable from another instance. AppSearchImpl appSearchImpl2 = - AppSearchImpl.create(appsearchDir, context, /*logger=*/ null); + AppSearchImpl.create( + appsearchDir, + context, + /*logger=*/ null, + ALWAYS_OPTIMIZE); expectThrows( AppSearchException.class, () -> @@ -1939,7 +1944,12 @@ public class AppSearchImplTest { // Setup the index Context context = ApplicationProvider.getApplicationContext(); File appsearchDir = mTemporaryFolder.newFolder(); - AppSearchImpl appSearchImpl = AppSearchImpl.create(appsearchDir, context, /*logger=*/ null); + AppSearchImpl appSearchImpl = + AppSearchImpl.create( + appsearchDir, + context, + /*logger=*/ null, + ALWAYS_OPTIMIZE); List<AppSearchSchema> schemas = Collections.singletonList(new AppSearchSchema.Builder("type").build()); @@ -1997,7 +2007,11 @@ public class AppSearchImplTest { // Only the second document should be retrievable from another instance. AppSearchImpl appSearchImpl2 = - AppSearchImpl.create(appsearchDir, context, /*logger=*/ null); + AppSearchImpl.create( + appsearchDir, + context, + /*logger=*/ null, + ALWAYS_OPTIMIZE); expectThrows( AppSearchException.class, () -> diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchLoggerTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchLoggerTest.java index f0a6ef13b212..c6726c69c7fd 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 @@ -53,6 +53,10 @@ public class AppSearchLoggerTest { @Rule public TemporaryFolder mTemporaryFolder = new TemporaryFolder(); private AppSearchImpl mAppSearchImpl; private TestLogger mLogger; + /** + * Always trigger optimize in this class. OptimizeStrategy will be tested in its own test class. + */ + private static final OptimizeStrategy ALWAYS_OPTIMIZE = optimizeInfo -> true; @Before public void setUp() throws Exception { @@ -63,7 +67,8 @@ public class AppSearchLoggerTest { AppSearchImpl.create( mTemporaryFolder.newFolder(), context, - /*logger=*/ null); + /*logger=*/ null, + ALWAYS_OPTIMIZE); mLogger = new TestLogger(); } @@ -286,11 +291,13 @@ public class AppSearchLoggerTest { public void testLoggingStats_initialize() throws Exception { Context context = ApplicationProvider.getApplicationContext(); + // Create an unused AppSearchImpl to generated an InitializeStats. AppSearchImpl appSearchImpl = AppSearchImpl.create( mTemporaryFolder.newFolder(), context, - mLogger); + mLogger, + ALWAYS_OPTIMIZE); InitializeStats iStats = mLogger.mInitializeStats; assertThat(iStats).isNotNull(); @@ -325,9 +332,9 @@ public class AppSearchLoggerTest { PutDocumentStats pStats = mLogger.mPutDocumentStats; assertThat(pStats).isNotNull(); - assertThat(pStats.getGeneralStats().getPackageName()).isEqualTo(testPackageName); - assertThat(pStats.getGeneralStats().getDatabase()).isEqualTo(testDatabase); - assertThat(pStats.getGeneralStats().getStatusCode()).isEqualTo(AppSearchResult.RESULT_OK); + assertThat(pStats.getPackageName()).isEqualTo(testPackageName); + assertThat(pStats.getDatabase()).isEqualTo(testDatabase); + assertThat(pStats.getStatusCode()).isEqualTo(AppSearchResult.RESULT_OK); // The rest of native stats have been tested in testCopyNativeStats assertThat(pStats.getNativeDocumentSizeBytes()).isGreaterThan(0); } diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/FrameworkOptimizeStrategyTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/FrameworkOptimizeStrategyTest.java new file mode 100644 index 000000000000..f30cbb8c5158 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/FrameworkOptimizeStrategyTest.java @@ -0,0 +1,68 @@ +/* + * Copyright 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.appsearch.external.localstorage; + +import static com.android.server.appsearch.external.localstorage.FrameworkOptimizeStrategy.BYTES_OPTIMIZE_THRESHOLD; +import static com.android.server.appsearch.external.localstorage.FrameworkOptimizeStrategy.DOC_COUNT_OPTIMIZE_THRESHOLD; +import static com.android.server.appsearch.external.localstorage.FrameworkOptimizeStrategy.TIME_OPTIMIZE_THRESHOLD_MILLIS; + +import static com.google.common.truth.Truth.assertThat; + +import com.android.server.appsearch.proto.GetOptimizeInfoResultProto; +import com.android.server.appsearch.proto.StatusProto; + +import org.junit.Test; + +public class FrameworkOptimizeStrategyTest { + FrameworkOptimizeStrategy mFrameworkOptimizeStrategy = new FrameworkOptimizeStrategy(); + + @Test + public void testShouldOptimize_docCountThreshold() { + GetOptimizeInfoResultProto optimizeInfo = + GetOptimizeInfoResultProto.newBuilder() + .setTimeSinceLastOptimizeMs(0) + .setEstimatedOptimizableBytes(BYTES_OPTIMIZE_THRESHOLD) + .setOptimizableDocs(0) + .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.OK).build()) + .build(); + assertThat(mFrameworkOptimizeStrategy.shouldOptimize(optimizeInfo)).isTrue(); + } + + @Test + public void testShouldOptimize_byteThreshold() { + GetOptimizeInfoResultProto optimizeInfo = + GetOptimizeInfoResultProto.newBuilder() + .setTimeSinceLastOptimizeMs(TIME_OPTIMIZE_THRESHOLD_MILLIS) + .setEstimatedOptimizableBytes(0) + .setOptimizableDocs(0) + .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.OK).build()) + .build(); + assertThat(mFrameworkOptimizeStrategy.shouldOptimize(optimizeInfo)).isTrue(); + } + + @Test + public void testShouldNotOptimize_timeThreshold() { + GetOptimizeInfoResultProto optimizeInfo = + GetOptimizeInfoResultProto.newBuilder() + .setTimeSinceLastOptimizeMs(0) + .setEstimatedOptimizableBytes(0) + .setOptimizableDocs(DOC_COUNT_OPTIMIZE_THRESHOLD) + .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.OK).build()) + .build(); + assertThat(mFrameworkOptimizeStrategy.shouldOptimize(optimizeInfo)).isTrue(); + } +} diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/stats/AppSearchStatsTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/stats/AppSearchStatsTest.java index a71e53233848..6d9068675a72 100644 --- a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/stats/AppSearchStatsTest.java +++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/stats/AppSearchStatsTest.java @@ -29,57 +29,28 @@ public class AppSearchStatsTest { static final int TEST_TOTAL_LATENCY_MILLIS = 20; @Test - public void testAppSearchStats_GeneralStats() { - final GeneralStats gStats = - new GeneralStats.Builder(TEST_PACKAGE_NAME, TEST_DATA_BASE) - .setStatusCode(TEST_STATUS_CODE) - .setTotalLatencyMillis(TEST_TOTAL_LATENCY_MILLIS) - .build(); - - assertThat(gStats.getPackageName()).isEqualTo(TEST_PACKAGE_NAME); - assertThat(gStats.getDatabase()).isEqualTo(TEST_DATA_BASE); - assertThat(gStats.getStatusCode()).isEqualTo(TEST_STATUS_CODE); - assertThat(gStats.getTotalLatencyMillis()).isEqualTo(TEST_TOTAL_LATENCY_MILLIS); - } - - /** Make sure status code is UNKNOWN if not set in {@link GeneralStats} */ - @Test - public void testAppSearchStats_GeneralStats_defaultStatsCode_Unknown() { - final GeneralStats gStats = - new GeneralStats.Builder(TEST_PACKAGE_NAME, TEST_DATA_BASE) - .setTotalLatencyMillis(TEST_TOTAL_LATENCY_MILLIS) - .build(); - - assertThat(gStats.getPackageName()).isEqualTo(TEST_PACKAGE_NAME); - assertThat(gStats.getDatabase()).isEqualTo(TEST_DATA_BASE); - assertThat(gStats.getStatusCode()).isEqualTo(AppSearchResult.RESULT_UNKNOWN_ERROR); - assertThat(gStats.getTotalLatencyMillis()).isEqualTo(TEST_TOTAL_LATENCY_MILLIS); - } - - @Test public void testAppSearchStats_CallStats() { final int estimatedBinderLatencyMillis = 1; final int numOperationsSucceeded = 2; final int numOperationsFailed = 3; final @CallStats.CallType int callType = CallStats.CALL_TYPE_PUT_DOCUMENTS; - final CallStats.Builder cStatsBuilder = - new CallStats.Builder(TEST_PACKAGE_NAME, TEST_DATA_BASE) + final CallStats cStats = + new CallStats.Builder() + .setPackageName(TEST_PACKAGE_NAME) + .setDatabase(TEST_DATA_BASE) + .setStatusCode(TEST_STATUS_CODE) + .setTotalLatencyMillis(TEST_TOTAL_LATENCY_MILLIS) .setCallType(callType) .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis) .setNumOperationsSucceeded(numOperationsSucceeded) - .setNumOperationsFailed(numOperationsFailed); - cStatsBuilder - .getGeneralStatsBuilder() - .setStatusCode(TEST_STATUS_CODE) - .setTotalLatencyMillis(TEST_TOTAL_LATENCY_MILLIS); - final CallStats cStats = cStatsBuilder.build(); + .setNumOperationsFailed(numOperationsFailed) + .build(); - assertThat(cStats.getGeneralStats().getPackageName()).isEqualTo(TEST_PACKAGE_NAME); - assertThat(cStats.getGeneralStats().getDatabase()).isEqualTo(TEST_DATA_BASE); - assertThat(cStats.getGeneralStats().getStatusCode()).isEqualTo(TEST_STATUS_CODE); - assertThat(cStats.getGeneralStats().getTotalLatencyMillis()) - .isEqualTo(TEST_TOTAL_LATENCY_MILLIS); + assertThat(cStats.getPackageName()).isEqualTo(TEST_PACKAGE_NAME); + assertThat(cStats.getDatabase()).isEqualTo(TEST_DATA_BASE); + assertThat(cStats.getStatusCode()).isEqualTo(TEST_STATUS_CODE); + assertThat(cStats.getTotalLatencyMillis()).isEqualTo(TEST_TOTAL_LATENCY_MILLIS); assertThat(cStats.getEstimatedBinderLatencyMillis()) .isEqualTo(estimatedBinderLatencyMillis); assertThat(cStats.getCallType()).isEqualTo(callType); @@ -88,6 +59,19 @@ public class AppSearchStatsTest { } @Test + public void testAppSearchCallStats_nullValues() { + final @CallStats.CallType int callType = CallStats.CALL_TYPE_PUT_DOCUMENTS; + + final CallStats.Builder cStatsBuilder = new CallStats.Builder().setCallType(callType); + + final CallStats cStats = cStatsBuilder.build(); + + assertThat(cStats.getPackageName()).isNull(); + assertThat(cStats.getDatabase()).isNull(); + assertThat(cStats.getCallType()).isEqualTo(callType); + } + + @Test public void testAppSearchStats_PutDocumentStats() { final int generateDocumentProtoLatencyMillis = 1; final int rewriteDocumentTypesLatencyMillis = 2; @@ -100,6 +84,8 @@ public class AppSearchStatsTest { final boolean nativeExceededMaxNumTokens = true; final PutDocumentStats.Builder pStatsBuilder = new PutDocumentStats.Builder(TEST_PACKAGE_NAME, TEST_DATA_BASE) + .setStatusCode(TEST_STATUS_CODE) + .setTotalLatencyMillis(TEST_TOTAL_LATENCY_MILLIS) .setGenerateDocumentProtoLatencyMillis(generateDocumentProtoLatencyMillis) .setRewriteDocumentTypesLatencyMillis(rewriteDocumentTypesLatencyMillis) .setNativeLatencyMillis(nativeLatencyMillis) @@ -109,17 +95,13 @@ public class AppSearchStatsTest { .setNativeDocumentSizeBytes(nativeDocumentSize) .setNativeNumTokensIndexed(nativeNumTokensIndexed) .setNativeExceededMaxNumTokens(nativeExceededMaxNumTokens); - pStatsBuilder - .getGeneralStatsBuilder() - .setStatusCode(TEST_STATUS_CODE) - .setTotalLatencyMillis(TEST_TOTAL_LATENCY_MILLIS); + final PutDocumentStats pStats = pStatsBuilder.build(); - assertThat(pStats.getGeneralStats().getPackageName()).isEqualTo(TEST_PACKAGE_NAME); - assertThat(pStats.getGeneralStats().getDatabase()).isEqualTo(TEST_DATA_BASE); - assertThat(pStats.getGeneralStats().getStatusCode()).isEqualTo(TEST_STATUS_CODE); - assertThat(pStats.getGeneralStats().getTotalLatencyMillis()) - .isEqualTo(TEST_TOTAL_LATENCY_MILLIS); + assertThat(pStats.getPackageName()).isEqualTo(TEST_PACKAGE_NAME); + assertThat(pStats.getDatabase()).isEqualTo(TEST_DATA_BASE); + assertThat(pStats.getStatusCode()).isEqualTo(TEST_STATUS_CODE); + assertThat(pStats.getTotalLatencyMillis()).isEqualTo(TEST_TOTAL_LATENCY_MILLIS); assertThat(pStats.getGenerateDocumentProtoLatencyMillis()) .isEqualTo(generateDocumentProtoLatencyMillis); assertThat(pStats.getRewriteDocumentTypesLatencyMillis()) 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 7e1639e83ea0..7c275e13e24a 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,6 +16,8 @@ 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; @@ -28,13 +30,12 @@ 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.ArrayMap; -import android.util.SparseIntArray; import androidx.test.core.app.ApplicationProvider; +import com.android.server.appsearch.AppSearchConfig; import com.android.server.appsearch.external.localstorage.stats.CallStats; import org.junit.Before; @@ -48,11 +49,14 @@ 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 final Map<UserHandle, PackageManager> mMockPackageManagers = new ArrayMap<>(); private Context mContext; @@ -73,66 +77,6 @@ public class PlatformLoggerTest { } @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 public void testCalculateHashCode_MD5_int32_shortString() throws NoSuchAlgorithmException, UnsupportedEncodingException { final String str1 = "d1"; @@ -202,87 +146,6 @@ public class PlatformLoggerTest { 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 { @@ -291,10 +154,7 @@ public class PlatformLoggerTest { PlatformLogger logger = new PlatformLogger( mContext, mContext.getUser(), - new PlatformLogger.Config( - TEST_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS, - TEST_DEFAULT_SAMPLING_INTERVAL, - /*samplingIntervals=*/ new SparseIntArray())); + AppSearchConfig.create(DIRECT_EXECUTOR)); PackageManager mockPackageManager = getMockPackageManager(mContext.getUser()); when(mockPackageManager.getPackageUid(testPackageName, /*flags=*/0)).thenReturn(testUid); 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 6f0c8e1004c4..aec70f4f3df0 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 @@ public class AuthServiceTest { 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 @@ public class AuthServiceTest { eq(authenticators)); } - @Test public void testHasEnrolledBiometrics_callsBiometricServiceHasEnrolledBiometrics() throws Exception { 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 654d9fcf9210..5447a58a1643 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 @@ public class DevicePolicyManagerTest extends DpmTestBase { 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 @@ public class DevicePolicyManagerTest extends DpmTestBase { 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 @@ public class DevicePolicyManagerTest extends DpmTestBase { 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 @@ public class DevicePolicyManagerTest extends DpmTestBase { 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 2e004683acdb..d10419d4bfc5 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 @@ public class DpmMockContext extends MockContext { 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 9cc057252a4c..8a2919d55216 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.media.IAudioService; 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 class MockSystemServices { 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 @@ public class MockSystemServices { 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 24e226a64917..a8f24ce5e11d 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 @@ package com.android.server.devicepolicy; 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.Context; 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 org.mockito.MockitoAnnotations; 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 @@ public class OverlayPackagesProviderTest { 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 @@ public class OverlayPackagesProviderTest { 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 @@ public class OverlayPackagesProviderTest { 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 @@ public class OverlayPackagesProviderTest { } 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/display/DisplayModeDirectorTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java index fb2db2259c7e..918979cdd859 100644 --- a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java +++ b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java @@ -854,7 +854,7 @@ public class DisplayModeDirectorTest { createDirectorFromRefreshRateArray(new float[] {60.f, 90.f, 110.f}, 0); verify(mStatusBarMock, never()).setUdfpsHbmListener(any()); - director.start(createMockSensorManager()); + director.onBootCompleted(); verify(mStatusBarMock).setUdfpsHbmListener(eq(director.getUdpfsObserver())); } @@ -863,6 +863,7 @@ public class DisplayModeDirectorTest { DisplayModeDirector director = createDirectorFromRefreshRateArray(new float[] {60.f, 90.f, 110.f}, 0); director.start(createMockSensorManager()); + director.onBootCompleted(); ArgumentCaptor<IUdfpsHbmListener> captor = ArgumentCaptor.forClass(IUdfpsHbmListener.class); verify(mStatusBarMock).setUdfpsHbmListener(captor.capture()); 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 c50648573d52..2a4896a7b041 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 @@ public final class DataManagerTest { 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 @@ public final class DataManagerTest { @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 @@ public final class DataManagerTest { 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 @@ public final class DataManagerTest { 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 @@ public final class DataManagerTest { 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 @@ public final class DataManagerTest { 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 @@ public final class DataManagerTest { 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 @@ public final class DataManagerTest { NotificationListenerService listenerService = mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY); - listenerService.onNotificationPosted(mStatusBarNotification); + sendGenericNotification(); shortcut.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS); mDataManager.addOrUpdateConversationInfo(shortcut); @@ -626,19 +637,13 @@ public final class DataManagerTest { 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 @@ public final class DataManagerTest { 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 @@ public final class DataManagerTest { 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 @@ public final class DataManagerTest { 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 @@ public final class DataManagerTest { 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 @@ public final class DataManagerTest { 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 @@ public final class DataManagerTest { 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 @@ public final class DataManagerTest { 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 @@ public final class DataManagerTest { 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 @@ public final class DataManagerTest { 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 @@ public final class DataManagerTest { 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 @@ public final class DataManagerTest { 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 @@ public final class DataManagerTest { // 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 @@ public final class DataManagerTest { 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 @@ public final class DataManagerTest { 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 @@ public final class DataManagerTest { 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 @@ public final class DataManagerTest { // 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 @@ public final class DataManagerTest { 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/ShortcutManagerTest2.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java index 7241fa00ecf7..90a127701505 100644 --- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java +++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java @@ -253,6 +253,7 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest { .setPerson(makePerson("person", "personKey", "personUri")) .setLongLived(true) .setExtras(pb) + .setStartingTheme(android.R.style.Theme_Black_NoTitleBar_Fullscreen) .build(); si.addFlags(ShortcutInfo.FLAG_PINNED); si.setBitmapPath("abc"); @@ -288,6 +289,8 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest { assertEquals(null, si.getTextResName()); assertEquals(0, si.getDisabledMessageResourceId()); assertEquals(null, si.getDisabledMessageResName()); + assertEquals("android:style/Theme.Black.NoTitleBar.Fullscreen", + si.getStartingThemeResName()); } public void testShortcutInfoParcel_resId() { @@ -308,6 +311,7 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest { .setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz")) .setRank(123) .setExtras(pb) + .setStartingTheme(android.R.style.Theme_Black_NoTitleBar_Fullscreen) .build(); si.addFlags(ShortcutInfo.FLAG_PINNED); si.setBitmapPath("abc"); @@ -339,6 +343,8 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest { assertEquals(456, si.getIconResourceId()); assertEquals("string/r456", si.getIconResName()); assertEquals("test_uri", si.getIconUri()); + assertEquals("android:style/Theme.Black.NoTitleBar.Fullscreen", + si.getStartingThemeResName()); } public void testShortcutInfoClone() { @@ -2210,6 +2216,10 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest { android.R.drawable.alert_dark_frame, true, getTestContext().getPackageName())); assertEquals("" + android.R.string.cancel, ShortcutInfo.lookUpResourceName(res, android.R.string.cancel, false, getTestContext().getPackageName())); + assertEquals("" + android.R.style.Theme_Black_NoTitleBar_Fullscreen, + ShortcutInfo.lookUpResourceName( + res, android.R.style.Theme_Black_NoTitleBar_Fullscreen, true, + getTestContext().getPackageName())); } public void testLookUpResourceName_appResources() { @@ -2236,6 +2246,10 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest { assertEquals(android.R.drawable.alert_dark_frame, ShortcutInfo.lookUpResourceId(res, "" + android.R.drawable.alert_dark_frame, null, getTestContext().getPackageName())); + assertEquals(android.R.style.Theme_Black_NoTitleBar_Fullscreen, + ShortcutInfo.lookUpResourceId( + res, "" + android.R.style.Theme_Black_NoTitleBar_Fullscreen, + null, getTestContext().getPackageName())); } // Test for a ShortcutInfo method. diff --git a/services/tests/servicestests/src/com/android/server/vibrator/DeviceVibrationEffectAdapterTest.java b/services/tests/servicestests/src/com/android/server/vibrator/DeviceVibrationEffectAdapterTest.java index 00b05d4ad10c..14cab021edb0 100644 --- a/services/tests/servicestests/src/com/android/server/vibrator/DeviceVibrationEffectAdapterTest.java +++ b/services/tests/servicestests/src/com/android/server/vibrator/DeviceVibrationEffectAdapterTest.java @@ -17,6 +17,7 @@ package com.android.server.vibrator; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import android.hardware.vibrator.IVibrator; import android.os.VibrationEffect; @@ -25,8 +26,11 @@ import android.os.vibrator.PrebakedSegment; import android.os.vibrator.PrimitiveSegment; import android.os.vibrator.RampSegment; import android.os.vibrator.StepSegment; +import android.os.vibrator.VibrationEffectSegment; import android.platform.test.annotations.Presubmit; +import androidx.test.InstrumentationRegistry; + import org.junit.Before; import org.junit.Test; @@ -58,7 +62,7 @@ public class DeviceVibrationEffectAdapterTest { @Before public void setUp() throws Exception { - mAdapter = new DeviceVibrationEffectAdapter(); + mAdapter = new DeviceVibrationEffectAdapter(InstrumentationRegistry.getContext()); } @Test @@ -84,28 +88,19 @@ public class DeviceVibrationEffectAdapterTest { new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 0.2f, /* startFrequency= */ -4, /* endFrequency= */ 2, /* duration= */ 10), new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.2f, - /* startFrequency= */ 0, /* endFrequency= */ 0, /* duration= */ 11), + /* startFrequency= */ 0, /* endFrequency= */ 0, /* duration= */ 100), new RampSegment(/* startAmplitude= */ 0.65f, /* endAmplitude= */ 0.65f, - /* startFrequency= */ 0, /* endFrequency= */ 1, /* duration= */ 200)), + /* startFrequency= */ 0, /* endFrequency= */ 1, /* duration= */ 1000)), /* repeatIndex= */ 3); - VibrationEffect.Composed expected = new VibrationEffect.Composed(Arrays.asList( - new StepSegment(/* amplitude= */ 0, Float.NaN, /* duration= */ 10), - new StepSegment(/* amplitude= */ 0.5f, Float.NaN, /* duration= */ 100), - // 10ms ramp becomes 2 steps - new StepSegment(/* amplitude= */ 1, Float.NaN, /* duration= */ 5), - new StepSegment(/* amplitude= */ 0.2f, Float.NaN, /* duration= */ 5), - // 11ms ramp becomes 3 steps - new StepSegment(/* amplitude= */ 0.8f, Float.NaN, /* duration= */ 5), - new StepSegment(/* amplitude= */ 0.6f, Float.NaN, /* duration= */ 5), - new StepSegment(/* amplitude= */ 0.2f, Float.NaN, /* duration= */ 1), - // 200ms ramp with same amplitude becomes a single step - new StepSegment(/* amplitude= */ 0.65f, Float.NaN, /* duration= */ 200)), - // Repeat index fixed after intermediate steps added - /* repeatIndex= */ 4); - - VibratorInfo info = createVibratorInfo(EMPTY_FREQUENCY_MAPPING); - assertEquals(expected, mAdapter.apply(effect, info)); + VibrationEffect.Composed adaptedEffect = (VibrationEffect.Composed) mAdapter.apply(effect, + createVibratorInfo(EMPTY_FREQUENCY_MAPPING)); + assertTrue(adaptedEffect.getSegments().size() > effect.getSegments().size()); + assertTrue(adaptedEffect.getRepeatIndex() >= effect.getRepeatIndex()); + + for (VibrationEffectSegment adaptedSegment : adaptedEffect.getSegments()) { + assertTrue(adaptedSegment instanceof StepSegment); + } } @Test @@ -136,33 +131,6 @@ public class DeviceVibrationEffectAdapterTest { } @Test - public void testStepAndRampSegments_withPwleCapabilityAndNoFrequency_keepsOriginalSteps() { - VibrationEffect.Composed effect = new VibrationEffect.Composed(Arrays.asList( - new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 10), - new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 100), - new PrimitiveSegment(VibrationEffect.Composition.PRIMITIVE_TICK, 1, 10), - new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 1, - /* startFrequency= */ -4, /* endFrequency= */ 2, /* duration= */ 50), - new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.2f, - /* startFrequency= */ 10, /* endFrequency= */ -5, /* duration= */ 20)), - /* repeatIndex= */ 2); - - VibrationEffect.Composed expected = new VibrationEffect.Composed(Arrays.asList( - new StepSegment(/* amplitude= */ 0, /* frequency= */ 150, /* duration= */ 10), - new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 150, /* duration= */ 100), - new PrimitiveSegment(VibrationEffect.Composition.PRIMITIVE_TICK, 1, 10), - new RampSegment(/* startAmplitude= */ 0.1f, /* endAmplitude= */ 0.8f, - /* startFrequency= */ 50, /* endFrequency= */ 200, /* duration= */ 50), - new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.1f, - /* startFrequency= */ 200, /* endFrequency= */ 50, /* duration= */ 20)), - /* repeatIndex= */ 2); - - VibratorInfo info = createVibratorInfo(TEST_FREQUENCY_MAPPING, - IVibrator.CAP_COMPOSE_PWLE_EFFECTS); - assertEquals(expected, mAdapter.apply(effect, info)); - } - - @Test public void testStepAndRampSegments_withEmptyFreqMapping_returnsSameAmplitudesAndZeroFreq() { VibrationEffect.Composed effect = new VibrationEffect.Composed(Arrays.asList( new StepSegment(/* amplitude= */ 0, /* frequency= */ 1, /* duration= */ 10), diff --git a/services/tests/servicestests/src/com/android/server/vibrator/RampToStepAdapterTest.java b/services/tests/servicestests/src/com/android/server/vibrator/RampToStepAdapterTest.java new file mode 100644 index 000000000000..95c3bd93e69b --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/vibrator/RampToStepAdapterTest.java @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.vibrator; + +import static org.junit.Assert.assertEquals; + +import android.hardware.vibrator.IVibrator; +import android.os.VibrationEffect; +import android.os.VibratorInfo; +import android.os.vibrator.PrebakedSegment; +import android.os.vibrator.PrimitiveSegment; +import android.os.vibrator.RampSegment; +import android.os.vibrator.StepSegment; +import android.os.vibrator.VibrationEffectSegment; +import android.platform.test.annotations.Presubmit; + +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.IntStream; + +/** + * Tests for {@link RampToStepAdapter}. + * + * Build/Install/Run: + * atest FrameworksServicesTests:RampToStepAdapterTest + */ +@Presubmit +public class RampToStepAdapterTest { + private static final int TEST_STEP_DURATION = 5; + + private RampToStepAdapter mAdapter; + + @Before + public void setUp() throws Exception { + mAdapter = new RampToStepAdapter(TEST_STEP_DURATION); + } + + @Test + public void testStepAndPrebakedAndPrimitiveSegments_keepsListUnchanged() { + List<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList( + new StepSegment(/* amplitude= */ 0, /* frequency= */ 1, /* duration= */ 10), + new PrebakedSegment( + VibrationEffect.EFFECT_CLICK, false, VibrationEffect.EFFECT_STRENGTH_LIGHT), + new PrimitiveSegment(VibrationEffect.Composition.PRIMITIVE_TICK, 1, 10))); + List<VibrationEffectSegment> originalSegments = new ArrayList<>(segments); + + assertEquals(-1, mAdapter.apply(segments, -1, createVibratorInfo())); + assertEquals(1, mAdapter.apply(segments, 1, createVibratorInfo())); + + assertEquals(originalSegments, segments); + } + + @Test + public void testRampSegments_withPwleCapability_keepsListUnchanged() { + List<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList( + new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 100), + new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.2f, + /* startFrequency= */ 10, /* endFrequency= */ -5, /* duration= */ 20))); + List<VibrationEffectSegment> originalSegments = new ArrayList<>(segments); + + VibratorInfo vibratorInfo = createVibratorInfo(IVibrator.CAP_COMPOSE_PWLE_EFFECTS); + assertEquals(-1, mAdapter.apply(segments, -1, vibratorInfo)); + assertEquals(0, mAdapter.apply(segments, 0, vibratorInfo)); + + assertEquals(originalSegments, segments); + } + + @Test + public void testRampSegments_withoutPwleCapability_convertsRampsToSteps() { + List<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList( + new StepSegment(/* amplitude= */ 0, /* frequency= */ 1, /* duration= */ 10), + new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 100), + new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 0.2f, + /* startFrequency= */ -4, /* endFrequency= */ 2, /* duration= */ 10), + new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.2f, + /* startFrequency= */ -3, /* endFrequency= */ 0, /* duration= */ 11), + new RampSegment(/* startAmplitude= */ 0.65f, /* endAmplitude= */ 0.65f, + /* startFrequency= */ 0, /* endFrequency= */ 1, /* duration= */ 200))); + + List<VibrationEffectSegment> expectedSegments = Arrays.asList( + new StepSegment(/* amplitude= */ 0, /* frequency= */ 1, /* duration= */ 10), + new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 100), + // 10ms ramp becomes 2 steps + new StepSegment(/* amplitude= */ 1, /* frequency= */ -4, /* duration= */ 5), + new StepSegment(/* amplitude= */ 0.2f, /* frequency= */ 2, /* duration= */ 5), + // 11ms ramp becomes 3 steps + new StepSegment(/* amplitude= */ 0.8f, /* frequency= */ -3, /* duration= */ 5), + new StepSegment(/* amplitude= */ 0.6f, /* frequency= */ -2, /* duration= */ 5), + new StepSegment(/* amplitude= */ 0.2f, /* frequency= */ 0, /* duration= */ 1), + // 200ms ramp with same amplitude becomes a single step + new StepSegment(/* amplitude= */ 0.65f, /* frequency= */ 0, /* duration= */ 200)); + + // Repeat index fixed after intermediate steps added + assertEquals(4, mAdapter.apply(segments, 3, createVibratorInfo())); + + assertEquals(expectedSegments, segments); + } + + private static VibratorInfo createVibratorInfo(int... capabilities) { + return new VibratorInfo.Builder(0) + .setCapabilities(IntStream.of(capabilities).reduce((a, b) -> a | b).orElse(0)) + .build(); + } +} diff --git a/services/tests/servicestests/src/com/android/server/vibrator/StepToRampAdapterTest.java b/services/tests/servicestests/src/com/android/server/vibrator/StepToRampAdapterTest.java new file mode 100644 index 000000000000..f4eb2ded5a9d --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/vibrator/StepToRampAdapterTest.java @@ -0,0 +1,312 @@ +/* + * 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.vibrator; + +import static org.junit.Assert.assertEquals; + +import android.hardware.vibrator.IVibrator; +import android.os.VibrationEffect; +import android.os.VibratorInfo; +import android.os.vibrator.PrebakedSegment; +import android.os.vibrator.PrimitiveSegment; +import android.os.vibrator.RampSegment; +import android.os.vibrator.StepSegment; +import android.os.vibrator.VibrationEffectSegment; +import android.platform.test.annotations.Presubmit; + +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.IntStream; + +/** + * Tests for {@link StepToRampAdapter}. + * + * Build/Install/Run: + * atest FrameworksServicesTests:StepToRampAdapterTest + */ +@Presubmit +public class StepToRampAdapterTest { + private StepToRampAdapter mAdapter; + + @Before + public void setUp() throws Exception { + mAdapter = new StepToRampAdapter(/* rampDownDuration= */ 0); + } + + @Test + public void testRampAndPrebakedAndPrimitiveSegments_returnsOriginalSegments() { + List<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList( + new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 0.2f, + /* startFrequency= */ -4, /* endFrequency= */ 2, /* duration= */ 10), + new PrebakedSegment( + VibrationEffect.EFFECT_CLICK, false, VibrationEffect.EFFECT_STRENGTH_LIGHT), + new PrimitiveSegment(VibrationEffect.Composition.PRIMITIVE_TICK, 1, 10))); + List<VibrationEffectSegment> originalSegments = new ArrayList<>(segments); + + assertEquals(-1, mAdapter.apply(segments, -1, createVibratorInfo())); + assertEquals(1, mAdapter.apply(segments, 1, createVibratorInfo())); + + assertEquals(originalSegments, segments); + } + + @Test + public void testStepAndRampSegments_withoutPwleCapability_keepsListUnchanged() { + mAdapter = new StepToRampAdapter(50); + + List<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList( + new StepSegment(/* amplitude= */ 0, /* frequency= */ 1, /* duration= */ 10), + new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.2f, + /* startFrequency= */ 10, /* endFrequency= */ -5, /* duration= */ 20))); + List<VibrationEffectSegment> originalSegments = new ArrayList<>(segments); + + assertEquals(-1, mAdapter.apply(segments, -1, createVibratorInfo())); + assertEquals(0, mAdapter.apply(segments, 0, createVibratorInfo())); + + assertEquals(originalSegments, segments); + } + + @Test + public void testStepAndRampSegments_withPwleCapabilityAndNoFrequency_keepsOriginalSteps() { + List<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList( + new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 10), + new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 100), + new PrimitiveSegment(VibrationEffect.Composition.PRIMITIVE_TICK, 1, 10), + new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 1, + /* startFrequency= */ -4, /* endFrequency= */ 2, /* duration= */ 50), + new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.2f, + /* startFrequency= */ 10, /* endFrequency= */ -5, /* duration= */ 20))); + List<VibrationEffectSegment> originalSegments = new ArrayList<>(segments); + + VibratorInfo vibratorInfo = createVibratorInfo(IVibrator.CAP_COMPOSE_PWLE_EFFECTS); + assertEquals(-1, mAdapter.apply(segments, -1, vibratorInfo)); + assertEquals(3, mAdapter.apply(segments, 3, vibratorInfo)); + + assertEquals(originalSegments, segments); + } + + @Test + public void testStepAndRampSegments_withPwleCapabilityAndStepNextToRamp_convertsStepsToRamps() { + List<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList( + new StepSegment(/* amplitude= */ 0, /* frequency= */ 1, /* duration= */ 10), + new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 100), + new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 1, + /* startFrequency= */ -4, /* endFrequency= */ 2, /* duration= */ 50), + new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.2f, + /* startFrequency= */ 10, /* endFrequency= */ -5, /* duration= */ 20), + new StepSegment(/* amplitude= */ 0.8f, /* frequency= */ -1, /* duration= */ 60))); + + List<VibrationEffectSegment> expectedSegments = Arrays.asList( + new RampSegment(/* startAmplitude= */ 0, /* endAmplitude*/ 0, + /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 10), + new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude= */ 0.5f, + /* startFrequency= */ 0, /* endFrequency= */ 0, /* duration= */ 100), + new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 1, + /* startFrequency= */ -4, /* endFrequency= */ 2, /* duration= */ 50), + new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.2f, + /* startFrequency= */ 10, /* endFrequency= */ -5, /* duration= */ 20), + new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.8f, + /* startFrequency= */ -1, /* endFrequency= */ -1, /* duration= */ 60)); + + VibratorInfo vibratorInfo = createVibratorInfo(IVibrator.CAP_COMPOSE_PWLE_EFFECTS); + assertEquals(-1, mAdapter.apply(segments, -1, vibratorInfo)); + assertEquals(2, mAdapter.apply(segments, 2, vibratorInfo)); + + assertEquals(expectedSegments, segments); + } + + @Test + public void testStepSegments_withPwleCapabilityAndFrequency_convertsStepsToRamps() { + List<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList( + new StepSegment(/* amplitude= */ 0, /* frequency= */ -1, /* duration= */ 10), + new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 1, /* duration= */ 100))); + List<VibrationEffectSegment> expectedSegments = Arrays.asList( + new RampSegment(/* startAmplitude= */ 0, /* endAmplitude*/ 0, + /* startFrequency= */ -1, /* endFrequency= */ -1, /* duration= */ 10), + new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude= */ 0.5f, + /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 100)); + + VibratorInfo vibratorInfo = createVibratorInfo(IVibrator.CAP_COMPOSE_PWLE_EFFECTS); + assertEquals(-1, mAdapter.apply(segments, -1, vibratorInfo)); + assertEquals(0, mAdapter.apply(segments, 0, vibratorInfo)); + + assertEquals(expectedSegments, segments); + } + + @Test + public void testStepSegments_withRampDownEndingAtNonZero_noRampDownAdded() { + int rampDownDuration = 50; + mAdapter = new StepToRampAdapter(rampDownDuration); + + List<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList( + new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 10), + new StepSegment(/* amplitude= */ 0.8f, /* frequency= */ 1, /* duration= */ 100))); + List<VibrationEffectSegment> expectedSegments = Arrays.asList( + new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude*/ 0.5f, + /* startFrequency= */ 0, /* endFrequency= */ 0, /* duration= */ 10), + new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.8f, + /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 100)); + + VibratorInfo vibratorInfo = createVibratorInfo(IVibrator.CAP_COMPOSE_PWLE_EFFECTS); + assertEquals(-1, mAdapter.apply(segments, -1, vibratorInfo)); + + assertEquals(expectedSegments, segments); + } + + @Test + public void testStepSegments_withRampDownAndShortZeroSegment_replaceWithRampDown() { + mAdapter = new StepToRampAdapter(50); + + List<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList( + new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ -1, /* duration= */ 10), + new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 20), + new StepSegment(/* amplitude= */ 1, /* frequency= */ 1, /* duration= */ 30))); + List<VibrationEffectSegment> expectedSegments = Arrays.asList( + new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude*/ 0.5f, + /* startFrequency= */ -1, /* endFrequency= */ -1, /* duration= */ 10), + new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude= */ 0, + /* startFrequency= */ -1, /* endFrequency= */ -1, /* duration= */ 20), + new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 1, + /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 30)); + + VibratorInfo vibratorInfo = createVibratorInfo(IVibrator.CAP_COMPOSE_PWLE_EFFECTS); + assertEquals(2, mAdapter.apply(segments, 2, vibratorInfo)); + + assertEquals(expectedSegments, segments); + } + + @Test + public void testStepSegments_withRampDownAndLongZeroSegment_splitAndAddRampDown() { + mAdapter = new StepToRampAdapter(50); + + List<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList( + new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ -1, /* duration= */ 10), + new StepSegment(/* amplitude= */ 0, /* frequency= */ 1, /* duration= */ 150), + new StepSegment(/* amplitude= */ 1, /* frequency= */ 1, /* duration= */ 30))); + List<VibrationEffectSegment> expectedSegments = Arrays.asList( + new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude*/ 0.5f, + /* startFrequency= */ -1, /* endFrequency= */ -1, /* duration= */ 10), + new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude= */ 0, + /* startFrequency= */ -1, /* endFrequency= */ -1, /* duration= */ 50), + new RampSegment(/* startAmplitude= */ 0, /* endAmplitude= */ 0, + /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 100), + new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 1, + /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 30)); + + VibratorInfo vibratorInfo = createVibratorInfo(IVibrator.CAP_COMPOSE_PWLE_EFFECTS); + // Repeat index fixed after intermediate steps added + assertEquals(3, mAdapter.apply(segments, 2, vibratorInfo)); + + assertEquals(expectedSegments, segments); + } + + @Test + public void testStepSegments_withRampDownAndNoZeroSegment_noRampDownAdded() { + mAdapter = new StepToRampAdapter(50); + + List<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList( + new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ -1, /* duration= */ 10), + new StepSegment(/* amplitude= */ 1, /* frequency= */ 1, /* duration= */ 30), + new PrimitiveSegment(VibrationEffect.Composition.PRIMITIVE_TICK, 1, 10))); + List<VibrationEffectSegment> expectedSegments = Arrays.asList( + new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude*/ 0.5f, + /* startFrequency= */ -1, /* endFrequency= */ -1, /* duration= */ 10), + new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 1, + /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 30), + new PrimitiveSegment(VibrationEffect.Composition.PRIMITIVE_TICK, 1, 10)); + + VibratorInfo vibratorInfo = createVibratorInfo(IVibrator.CAP_COMPOSE_PWLE_EFFECTS); + assertEquals(-1, mAdapter.apply(segments, -1, vibratorInfo)); + + assertEquals(expectedSegments, segments); + } + + @Test + public void testStepSegments_withRampDownAndRepeatToNonZeroSegment_noRampDownAdded() { + mAdapter = new StepToRampAdapter(50); + + List<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList( + new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ -1, /* duration= */ 10), + new StepSegment(/* amplitude= */ 1, /* frequency= */ 1, /* duration= */ 30))); + List<VibrationEffectSegment> expectedSegments = Arrays.asList( + new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude*/ 0.5f, + /* startFrequency= */ -1, /* endFrequency= */ -1, /* duration= */ 10), + new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 1, + /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 30)); + + VibratorInfo vibratorInfo = createVibratorInfo(IVibrator.CAP_COMPOSE_PWLE_EFFECTS); + assertEquals(0, mAdapter.apply(segments, 0, vibratorInfo)); + + assertEquals(expectedSegments, segments); + } + + @Test + public void testStepSegments_withRampDownAndRepeatToShortZeroSegment_skipAndAppendRampDown() { + mAdapter = new StepToRampAdapter(50); + + List<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList( + new StepSegment(/* amplitude= */ 0, /* frequency= */ 1, /* duration= */ 20), + new StepSegment(/* amplitude= */ 1, /* frequency= */ 1, /* duration= */ 30))); + List<VibrationEffectSegment> expectedSegments = Arrays.asList( + new RampSegment(/* startAmplitude= */ 0, /* endAmplitude*/ 0, + /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 20), + new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 1, + /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 30), + new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 0, + /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 20)); + + VibratorInfo vibratorInfo = createVibratorInfo(IVibrator.CAP_COMPOSE_PWLE_EFFECTS); + // Shift repeat index to the right to use append instead of zero segment. + assertEquals(1, mAdapter.apply(segments, 0, vibratorInfo)); + + assertEquals(expectedSegments, segments); + } + + @Test + public void testStepSegments_withRampDownAndRepeatToLongZeroSegment_splitAndAppendRampDown() { + mAdapter = new StepToRampAdapter(50); + + List<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList( + new StepSegment(/* amplitude= */ 0, /* frequency= */ 1, /* duration= */ 120), + new StepSegment(/* amplitude= */ 1, /* frequency= */ 1, /* duration= */ 30))); + List<VibrationEffectSegment> expectedSegments = Arrays.asList( + // Split long zero segment to skip part of it. + new RampSegment(/* startAmplitude= */ 0, /* endAmplitude*/ 0, + /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 50), + new RampSegment(/* startAmplitude= */ 0, /* endAmplitude*/ 0, + /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 70), + new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 1, + /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 30), + new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 0, + /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 50)); + + VibratorInfo vibratorInfo = createVibratorInfo(IVibrator.CAP_COMPOSE_PWLE_EFFECTS); + // Shift repeat index to the right to use append with part of the zero segment. + assertEquals(1, mAdapter.apply(segments, 0, vibratorInfo)); + + assertEquals(expectedSegments, segments); + } + + private static VibratorInfo createVibratorInfo(int... capabilities) { + return new VibratorInfo.Builder(0) + .setCapabilities(IntStream.of(capabilities).reduce((a, b) -> a | b).orElse(0)) + .build(); + } +} diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java index ac3e05d27962..f02e2f081e3b 100644 --- a/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java +++ b/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java @@ -31,6 +31,7 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.content.Context; import android.hardware.vibrator.Braking; import android.hardware.vibrator.IVibrator; import android.hardware.vibrator.IVibratorManager; @@ -98,13 +99,17 @@ public class VibrationThreadTest { private IBatteryStats mIBatteryStatsMock; private final Map<Integer, FakeVibratorControllerProvider> mVibratorProviders = new HashMap<>(); + private DeviceVibrationEffectAdapter mEffectAdapter; private PowerManager.WakeLock mWakeLock; private TestLooper mTestLooper; @Before public void setUp() throws Exception { mTestLooper = new TestLooper(); - mWakeLock = InstrumentationRegistry.getContext().getSystemService( + + Context context = InstrumentationRegistry.getContext(); + mEffectAdapter = new DeviceVibrationEffectAdapter(context); + mWakeLock = context.getSystemService( PowerManager.class).newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*vibrator*"); mockVibrators(VIBRATOR_ID); @@ -985,8 +990,8 @@ public class VibrationThreadTest { } private VibrationThread startThreadAndDispatcher(Vibration vib) { - VibrationThread thread = new VibrationThread(vib, createVibratorControllers(), mWakeLock, - mIBatteryStatsMock, mThreadCallbacks); + VibrationThread thread = new VibrationThread(vib, mEffectAdapter, + createVibratorControllers(), mWakeLock, mIBatteryStatsMock, mThreadCallbacks); doAnswer(answer -> { thread.vibratorComplete(answer.getArgument(0)); return null; diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java index 5614aa2a165d..577e36c7d5db 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java @@ -394,7 +394,7 @@ public class NotificationListenerServiceTest extends UiServiceTestCase { "disabledMessage", 0, "disabledMessageResName", null, null, 0, null, 0, 0, 0, "iconResName", "bitmapPath", null, 0, - null, null, 0); + null, null, null); return si; } 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 2c7c3e3d0a87..70ba2cf17880 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_ 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 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { @Mock private ShortcutServiceInternal mShortcutServiceInternal; @Mock + private UserManager mUserManager; + @Mock ActivityManager mActivityManager; @Mock Resources mResources; @@ -526,6 +530,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { mShortcutHelper = mService.getShortcutHelper(); mShortcutHelper.setLauncherApps(mLauncherApps); mShortcutHelper.setShortcutServiceInternal(mShortcutServiceInternal); + mShortcutHelper.setUserManager(mUserManager); // Capture PackageIntentReceiver ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor = @@ -567,6 +572,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { 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 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { 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 f43e5a83c95d..11cb150651aa 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.ShortcutInfo; 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 @@ public class ShortcutHelperTest extends UiServiceTestCase { @Mock ShortcutHelper.ShortcutListener mShortcutListener; @Mock + UserManager mUserManager; + @Mock ShortcutServiceInternal mShortcutServiceInternal; @Mock NotificationRecord mNr; @@ -92,11 +95,12 @@ public class ShortcutHelperTest extends UiServiceTestCase { 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 @@ public class ShortcutHelperTest extends UiServiceTestCase { .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 82c459c6868a..38466ebaa0cf 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java @@ -38,6 +38,7 @@ import static org.mockito.Mockito.timeout; import android.app.ActivityOptions; import android.app.ActivityOptions.SourceInfo; import android.app.WaitResult; +import android.app.WindowConfiguration; import android.content.Intent; import android.os.IBinder; import android.os.SystemClock; @@ -476,6 +477,18 @@ public class ActivityMetricsLaunchObserverTests extends WindowTestsBase { transitToDrawnAndVerifyOnLaunchFinished(activityOnNewDisplay); } + @Test + public void testConsecutiveLaunchWithDifferentWindowingMode() { + mTopActivity.setWindowingMode(WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW); + onActivityLaunched(mTrampolineActivity); + mActivityMetricsLogger.notifyActivityLaunching(mTopActivity.intent, + mTrampolineActivity /* caller */, mTrampolineActivity.getUid()); + notifyActivityLaunched(START_SUCCESS, mTopActivity); + // Different windowing modes should be independent launch events. + transitToDrawnAndVerifyOnLaunchFinished(mTrampolineActivity); + transitToDrawnAndVerifyOnLaunchFinished(mTopActivity); + } + private void transitToDrawnAndVerifyOnLaunchFinished(ActivityRecord activity) { notifyTransitionStarting(activity); notifyWindowsDrawn(activity); 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 1ee646c57b14..e6348a50566c 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.junit.Assert.assertNotNull; 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 @@ public class FrameRateSelectionPriorityTests extends WindowTestsBase { 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 @@ public class FrameRateSelectionPriorityTests extends WindowTestsBase { @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 @@ public class FrameRateSelectionPriorityTests extends WindowTestsBase { @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 @@ public class FrameRateSelectionPriorityTests extends WindowTestsBase { @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 @@ public class FrameRateSelectionPriorityTests extends WindowTestsBase { @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 @@ public class FrameRateSelectionPriorityTests extends WindowTestsBase { @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 @@ public class FrameRateSelectionPriorityTests extends WindowTestsBase { @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 @@ public class FrameRateSelectionPriorityTests extends WindowTestsBase { 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/TestIWindow.java b/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java index b3a07454c1a0..4c31ee2ae5fa 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 @@ public class TestIWindow extends IWindow.Stub { } @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/WindowOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java index 3f1248a5fff7..a1b3159825fb 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java @@ -796,6 +796,9 @@ public class WindowOrganizerTests extends WindowTestsBase { @Override public void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) { } + @Override + public void onAppSplashScreenViewRemoved(int taskId) { + } }; private ActivityRecord makePipableActivity() { diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java index 31825013604d..17303a4aa7e1 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.AudioFormat; 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.HotwordRejectedResult; 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.annotations.GuardedBy; 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 @@ final class HotwordDetectionConnection { 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); @@ -148,8 +156,9 @@ final class HotwordDetectionConnection { updateStateLocked(options, sharedMemory); return; } - updateStateWithCallbackLocked(options, sharedMemory, callback); + updateAudioFlinger(); updateContentCaptureManager(); + updateStateWithCallbackLocked(options, sharedMemory, callback); } private void updateStateWithCallbackLocked(PersistableBundle options, @@ -164,7 +173,15 @@ final class HotwordDetectionConnection { 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)) { @@ -213,6 +230,15 @@ final class HotwordDetectionConnection { }); } + 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); @@ -235,6 +261,9 @@ final class HotwordDetectionConnection { if (mBound) { mRemoteHotwordDetectionService.unbind(); mBound = false; + LocalServices.getService(PermissionManagerServiceInternal.class) + .setHotwordDetectionServiceProvider(null); + mIdentity = null; } } @@ -329,7 +358,7 @@ final class HotwordDetectionConnection { if (DEBUG) { Slog.d(TAG, "onDetected"); } - externalCallback.onKeyphraseDetected(recognitionEvent); + externalCallback.onKeyphraseDetected(recognitionEvent, result); } @Override @@ -362,8 +391,7 @@ final class HotwordDetectionConnection { if (DEBUG) { Slog.d(TAG, "onDetected"); } - // TODO: Propagate the HotwordDetectedResult. - externalCallback.onKeyphraseDetected(recognitionEvent); + externalCallback.onKeyphraseDetected(recognitionEvent, result); } @Override @@ -407,7 +435,7 @@ final class HotwordDetectionConnection { 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 f3d80b13f290..bc812c2ae4a7 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 @@ public class VoiceInteractionManagerService extends SystemService { 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 @@ public class VoiceInteractionManagerService extends SystemService { class VoiceInteractionManagerServiceStub extends IVoiceInteractionManagerService.Stub { - VoiceInteractionManagerServiceImpl mImpl; + volatile VoiceInteractionManagerServiceImpl mImpl; private boolean mSafeMode; private int mCurUser; @@ -542,11 +562,10 @@ public class VoiceInteractionManagerService extends SystemService { } void switchImplementationIfNeededLocked(boolean force) { - if (!mCurUserSupported || mTemporarilyDisabled) { + if (!mCurUserSupported) { if (DEBUG_USER) { Slog.d(TAG, "switchImplementationIfNeeded(): skipping: force= " + force - + "mCurUserSupported=" + mCurUserSupported - + "mTemporarilyDisabled=" + mTemporarilyDisabled); + + "mCurUserSupported=" + mCurUserSupported); } if (mImpl != null) { mImpl.shutdownLocked(); @@ -1028,13 +1047,16 @@ public class VoiceInteractionManagerService extends SystemService { if (DEBUG) Slog.d(TAG, "setDisabled(): already " + disabled); return; } - Slog.i(TAG, "setDisabled(): changing to " + disabled); - final long caller = Binder.clearCallingIdentity(); - try { - mTemporarilyDisabled = disabled; - switchImplementationIfNeeded(/* force= */ false); - } finally { - Binder.restoreCallingIdentity(caller); + mTemporarilyDisabled = disabled; + if (mTemporarilyDisabled) { + Slog.i(TAG, "setDisabled(): temporarily disabling and hiding current session"); + try { + hideCurrentSession(); + } catch (RemoteException e) { + Log.w(TAG, "Failed to call hideCurrentSession", e); + } + } else { + Slog.i(TAG, "setDisabled(): re-enabling"); } } } @@ -1488,12 +1510,20 @@ public class VoiceInteractionManagerService extends SystemService { public boolean showSessionForActiveService(Bundle args, int sourceFlags, IVoiceInteractionSessionShowCallback showCallback, IBinder activityToken) { enforceCallingPermission(Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE); + if (DEBUG_USER) Slog.d(TAG, "showSessionForActiveService()"); + synchronized (this) { if (mImpl == null) { Slog.w(TAG, "showSessionForActiveService without running voice interaction" + "service"); return false; } + if (mTemporarilyDisabled) { + Slog.i(TAG, "showSessionForActiveService(): ignored while temporarily " + + "disabled"); + return false; + } + final long caller = Binder.clearCallingIdentity(); try { return mImpl.showSessionLocked(args, @@ -1510,22 +1540,21 @@ public class VoiceInteractionManagerService extends SystemService { @Override public void hideCurrentSession() throws RemoteException { enforceCallingPermission(Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE); - synchronized (this) { - if (mImpl == null) { - return; - } - final long caller = Binder.clearCallingIdentity(); - try { - if (mImpl.mActiveSession != null && mImpl.mActiveSession.mSession != null) { - try { - mImpl.mActiveSession.mSession.closeSystemDialogs(); - } catch (RemoteException e) { - Log.w(TAG, "Failed to call closeSystemDialogs", e); - } + + if (mImpl == null) { + return; + } + final long caller = Binder.clearCallingIdentity(); + try { + if (mImpl.mActiveSession != null && mImpl.mActiveSession.mSession != null) { + try { + mImpl.mActiveSession.mSession.closeSystemDialogs(); + } catch (RemoteException e) { + Log.w(TAG, "Failed to call closeSystemDialogs", e); } - } finally { - Binder.restoreCallingIdentity(caller); } + } finally { + Binder.restoreCallingIdentity(caller); } } diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java index 2206b0a61b9e..ca30bc51e046 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 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne final ComponentName mHotwordDetectionComponentName; boolean mBound = false; IVoiceInteractionService mService; - HotwordDetectionConnection mHotwordDetectionConnection; + volatile HotwordDetectionConnection mHotwordDetectionConnection; VoiceInteractionSessionConnection mActiveSession; int mDisabledShowContext; @@ -447,8 +447,8 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne 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/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceShellCommand.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceShellCommand.java index 6c355a3b4b30..2e3ca0157a3b 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceShellCommand.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceShellCommand.java @@ -71,6 +71,7 @@ final class VoiceInteractionManagerServiceShellCommand extends ShellCommand { pw.println(""); pw.println(" hide"); pw.println(" Hides the current session"); + pw.println(""); pw.println(" disable [true|false]"); pw.println(" Temporarily disable (when true) service"); pw.println(""); diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index c9996fb7141e..7f1ea8fa9614 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -33,6 +33,7 @@ import android.os.PersistableBundle; 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 @@ public class CarrierConfigManager { "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 = @@ -5148,6 +5164,7 @@ public class CarrierConfigManager { 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, diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/PictureCaptureDemo.java b/tests/HwAccelerationTest/src/com/android/test/hwui/PictureCaptureDemo.java index 029e302d0382..15568ac72227 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.ImageView; 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 @@ public class PictureCaptureDemo extends Activity { 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 @@ public class PictureCaptureDemo extends Activity { 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 @@ public class PictureCaptureDemo extends Activity { @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 @@ public class PictureCaptureDemo extends Activity { } }); } - - 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 9fd190cc12fe..ccd63f94de54 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 @@ public class StagedInstallInternalTest extends BaseHostJUnit4Test { * 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 @@ public class StagedInstallInternalTest extends BaseHostJUnit4Test { } @Test + @LargeTest public void testOrphanedStagingDirectoryGetsCleanedUpOnReboot() throws Exception { //create random directories in /data/app-staging folder getDevice().enableAdbRoot(); @@ -305,6 +307,7 @@ public class StagedInstallInternalTest extends BaseHostJUnit4Test { } @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 ea5a43104bba..e07fbbf7a1c1 100644 --- a/tests/UpdatableSystemFontTest/Android.bp +++ b/tests/UpdatableSystemFontTest/Android.bp @@ -27,6 +27,7 @@ android_test { 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 5d8f5fc2da93..8c3d87698e17 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 000000000000..b9a91490f517 --- /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 80b0dfeb8804..6bd07d0a84fd 100644 --- a/tests/UpdatableSystemFontTest/src/com/android/updatablesystemfont/UpdatableSystemFontTest.java +++ b/tests/UpdatableSystemFontTest/src/com/android/updatablesystemfont/UpdatableSystemFontTest.java @@ -40,6 +40,9 @@ import android.util.Pair; 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 @@ public class UpdatableSystemFontTest { 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 @@ public class UpdatableSystemFontTest { private String mKeyId; private FontManager mFontManager; + private UiDevice mUiDevice; @Before public void setUp() throws Exception { @@ -120,6 +127,7 @@ public class UpdatableSystemFontTest { mKeyId = insertCert(CERT_PATH); mFontManager = context.getSystemService(FontManager.class); expectCommandToSucceed("cmd font clear"); + mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); } @After @@ -287,6 +295,19 @@ public class UpdatableSystemFontTest { 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/com/android/server/VcnManagementServiceTest.java b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java index 3360d40062a3..b7a6d0ff7607 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.app.AppOpsManager; 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 @@ public class VcnManagementServiceTest { @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 @@ public class VcnManagementServiceTest { @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 @@ public class VcnManagementServiceTest { @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()); } |