Merge "Revert "Create non-bypassable op restrictions"" into sc-dev
diff --git a/Android.bp b/Android.bp
index 7c9cdcf..4a22369 100644
--- a/Android.bp
+++ b/Android.bp
@@ -313,6 +313,7 @@
libs: [
"app-compat-annotations",
"ext",
+ "framework-connectivity-annotations",
"framework-updatable-stubs-module_libs_api",
"unsupportedappusage",
],
@@ -326,6 +327,7 @@
"av-types-aidl-java",
"tv_tuner_resource_manager_aidl_interface-java",
"soundtrigger_middleware-aidl-java",
+ "modules-utils-preconditions",
"modules-utils-os",
"framework-permission-aidl-java",
],
@@ -409,6 +411,7 @@
srcs: [
// TODO: remove these annotations as soon as we can use andoid.support.annotations.*
":framework-annotations",
+ ":modules-utils-preconditions-srcs",
"core/java/android/net/DhcpResults.java",
"core/java/android/util/IndentingPrintWriter.java",
"core/java/android/util/LocalLog.java",
@@ -416,7 +419,6 @@
"core/java/com/android/internal/util/IndentingPrintWriter.java",
"core/java/com/android/internal/util/IState.java",
"core/java/com/android/internal/util/MessageUtils.java",
- "core/java/com/android/internal/util/Preconditions.java",
"core/java/com/android/internal/util/RingBufferIndices.java",
"core/java/com/android/internal/util/State.java",
"core/java/com/android/internal/util/StateMachine.java",
@@ -446,11 +448,11 @@
sdk_version: "module_current",
min_sdk_version: "30",
srcs: [
+ ":modules-utils-preconditions-srcs",
"core/java/android/os/HandlerExecutor.java",
"core/java/com/android/internal/util/AsyncChannel.java",
"core/java/com/android/internal/util/AsyncService.java",
"core/java/com/android/internal/util/Protocol.java",
- "core/java/com/android/internal/util/Preconditions.java",
"telephony/java/android/telephony/Annotation.java",
":net-utils-framework-wifi-common-srcs",
],
diff --git a/StubLibraries.bp b/StubLibraries.bp
index 4d5b09f..ed24d43 100644
--- a/StubLibraries.bp
+++ b/StubLibraries.bp
@@ -255,7 +255,7 @@
modules_system_stubs = [
"android.net.ipsec.ike.stubs.system",
- "art.module.public.api.stubs",
+ "art.module.public.api.stubs", // Only has public stubs
"conscrypt.module.public.api.stubs", // Only has public stubs
"framework-appsearch.stubs.system",
"framework-connectivity.stubs.system",
diff --git a/apct-tests/perftests/core/src/android/text/SystemFontsPerfTest.java b/apct-tests/perftests/core/src/android/text/SystemFontsPerfTest.java
new file mode 100644
index 0000000..5d744cd
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/text/SystemFontsPerfTest.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.text;
+
+import android.graphics.fonts.SystemFonts;
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+
+@LargeTest
+@RunWith(AndroidJUnit4.class)
+public class SystemFontsPerfTest {
+ @Rule
+ public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+ @Test
+ public void getAvailableFonts() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ state.pauseTiming();
+ SystemFonts.resetAvailableFonts();
+ System.gc();
+ state.resumeTiming();
+
+ SystemFonts.getAvailableFonts();
+ }
+ }
+}
diff --git a/apex/appsearch/framework/Android.bp b/apex/appsearch/framework/Android.bp
index f92f44b..b8fce4f 100644
--- a/apex/appsearch/framework/Android.bp
+++ b/apex/appsearch/framework/Android.bp
@@ -52,14 +52,18 @@
java_sdk_library {
name: "framework-appsearch",
srcs: [":framework-appsearch-sources"],
- sdk_version: "core_platform", // TODO(b/146218515) should be module_current
- impl_only_libs: ["framework-minus-apex"], // TODO(b/146218515) should be removed
+ sdk_version: "module_current",
+ static_libs: [
+ // This list must be kept in sync with jarjar.txt
+ "modules-utils-preconditions",
+ ],
libs: ["unsupportedappusage"], // TODO(b/181887768) should be removed
defaults: ["framework-module-defaults"],
permitted_packages: ["android.app.appsearch"],
aidl: {
include_dirs: ["frameworks/base/core/java"], // TODO(b/146218515) should be removed
},
+ jarjar_rules: "jarjar-rules.txt",
apex_available: ["com.android.appsearch"],
unsafe_ignore_missing_latest_api: true, // TODO(b/146218515) should be removed
}
diff --git a/apex/appsearch/framework/api/current.txt b/apex/appsearch/framework/api/current.txt
index 5a2f702..30fb4c6 100644
--- a/apex/appsearch/framework/api/current.txt
+++ b/apex/appsearch/framework/api/current.txt
@@ -98,13 +98,13 @@
method @NonNull public android.app.appsearch.AppSearchSchema.DoublePropertyConfig.Builder setCardinality(int);
}
- public static final class AppSearchSchema.Int64PropertyConfig extends android.app.appsearch.AppSearchSchema.PropertyConfig {
+ public static final class AppSearchSchema.LongPropertyConfig extends android.app.appsearch.AppSearchSchema.PropertyConfig {
}
- public static final class AppSearchSchema.Int64PropertyConfig.Builder {
- ctor public AppSearchSchema.Int64PropertyConfig.Builder(@NonNull String);
- method @NonNull public android.app.appsearch.AppSearchSchema.Int64PropertyConfig build();
- method @NonNull public android.app.appsearch.AppSearchSchema.Int64PropertyConfig.Builder setCardinality(int);
+ public static final class AppSearchSchema.LongPropertyConfig.Builder {
+ ctor public AppSearchSchema.LongPropertyConfig.Builder(@NonNull String);
+ method @NonNull public android.app.appsearch.AppSearchSchema.LongPropertyConfig build();
+ method @NonNull public android.app.appsearch.AppSearchSchema.LongPropertyConfig.Builder setCardinality(int);
}
public abstract static class AppSearchSchema.PropertyConfig {
diff --git a/apex/appsearch/framework/jarjar-rules.txt b/apex/appsearch/framework/jarjar-rules.txt
new file mode 100644
index 0000000..50c3ee4
--- /dev/null
+++ b/apex/appsearch/framework/jarjar-rules.txt
@@ -0,0 +1,6 @@
+# Rename all com.android.internal.util classes to prevent class name collisions
+# between this module and the other versions of the utility classes linked into
+# the framework.
+
+# These must be kept in sync with the sources of framework-utils-appsearch
+rule com.android.internal.util.Preconditions* android.app.appsearch.internal.util.Preconditions@1
diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java
index bc3c79f..59b940a 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java
@@ -205,7 +205,7 @@
AppSearchSession.createSearchSession(
searchContext,
mService,
- mContext.getUserId(),
+ mContext.getUser().getIdentifier(),
getPackageName(),
executor,
callback);
@@ -228,7 +228,7 @@
Objects.requireNonNull(executor);
Objects.requireNonNull(callback);
GlobalSearchSession.createGlobalSearchSession(
- mService, mContext.getUserId(), getPackageName(), executor, callback);
+ mService, mContext.getUser().getIdentifier(), getPackageName(), executor, callback);
}
/** Returns the package name that should be used for uid verification. */
diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java
index 5910130..43bf08d 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java
@@ -90,17 +90,20 @@
@NonNull @CallbackExecutor Executor executor,
@NonNull Consumer<AppSearchResult<AppSearchSession>> callback) {
try {
- mService.initialize(mUserId, new IAppSearchResultCallback.Stub() {
- @Override
- public void onResult(AppSearchResultParcel resultParcel) {
- executor.execute(() -> {
- AppSearchResult<Void> result = resultParcel.getResult();
- if (result.isSuccess()) {
- callback.accept(
- AppSearchResult.newSuccessfulResult(AppSearchSession.this));
- } else {
- callback.accept(AppSearchResult.newFailedResult(result));
- }
+ mService.initialize(mUserId,
+ /*binderCallStartTimeMillis=*/ SystemClock.elapsedRealtime(),
+ new IAppSearchResultCallback.Stub() {
+ @Override
+ public void onResult(AppSearchResultParcel resultParcel) {
+ executor.execute(() -> {
+ AppSearchResult<Void> result = resultParcel.getResult();
+ if (result.isSuccess()) {
+ callback.accept(
+ AppSearchResult.newSuccessfulResult(
+ AppSearchSession.this));
+ } else {
+ callback.accept(AppSearchResult.newFailedResult(result));
+ }
});
}
});
@@ -350,6 +353,7 @@
new ArrayList<>(request.getIds()),
request.getProjectionsInternal(),
mUserId,
+ /*binderCallStartTimeMillis=*/ SystemClock.elapsedRealtime(),
new IAppSearchBatchResultCallback.Stub() {
@Override
public void onResult(AppSearchBatchResultParcel resultParcel) {
@@ -563,6 +567,7 @@
try {
mService.removeByDocumentId(mPackageName, mDatabaseName, request.getNamespace(),
new ArrayList<>(request.getIds()), mUserId,
+ /*binderCallStartTimeMillis=*/ SystemClock.elapsedRealtime(),
new IAppSearchBatchResultCallback.Stub() {
@Override
public void onResult(AppSearchBatchResultParcel resultParcel) {
@@ -613,6 +618,7 @@
try {
mService.removeByQuery(mPackageName, mDatabaseName, queryExpression,
searchSpec.getBundle(), mUserId,
+ /*binderCallStartTimeMillis=*/ SystemClock.elapsedRealtime(),
new IAppSearchResultCallback.Stub() {
@Override
public void onResult(AppSearchResultParcel resultParcel) {
@@ -672,7 +678,8 @@
public void close() {
if (mIsMutated && !mIsClosed) {
try {
- mService.persistToDisk(mUserId);
+ mService.persistToDisk(mUserId,
+ /*binderCallStartTimeMillis=*/ SystemClock.elapsedRealtime());
mIsClosed = true;
} catch (RemoteException e) {
Log.e(TAG, "Unable to close the AppSearchSession", e);
@@ -702,6 +709,7 @@
request.isForceOverride(),
request.getVersion(),
mUserId,
+ /*binderCallStartTimeMillis=*/ SystemClock.elapsedRealtime(),
new IAppSearchResultCallback.Stub() {
@Override
public void onResult(AppSearchResultParcel resultParcel) {
@@ -789,6 +797,7 @@
/*forceOverride=*/ false,
request.getVersion(),
mUserId,
+ /*binderCallStartTimeMillis=*/ SystemClock.elapsedRealtime(),
new IAppSearchResultCallback.Stub() {
@Override
public void onResult(AppSearchResultParcel resultParcel) {
@@ -840,6 +849,7 @@
/*forceOverride=*/ true,
request.getVersion(),
mUserId,
+ /*binderCallStartTimeMillis=*/ SystemClock.elapsedRealtime(),
new IAppSearchResultCallback.Stub() {
@Override
public void onResult(AppSearchResultParcel resultParcel) {
diff --git a/apex/appsearch/framework/java/android/app/appsearch/GlobalSearchSession.java b/apex/appsearch/framework/java/android/app/appsearch/GlobalSearchSession.java
index 7d246c2..bb8d565 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/GlobalSearchSession.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/GlobalSearchSession.java
@@ -23,6 +23,7 @@
import android.app.appsearch.aidl.IAppSearchManager;
import android.app.appsearch.aidl.IAppSearchResultCallback;
import android.os.RemoteException;
+import android.os.SystemClock;
import android.util.Log;
import com.android.internal.util.Preconditions;
@@ -72,17 +73,20 @@
@NonNull @CallbackExecutor Executor executor,
@NonNull Consumer<AppSearchResult<GlobalSearchSession>> callback) {
try {
- mService.initialize(mUserId, new IAppSearchResultCallback.Stub() {
- @Override
- public void onResult(AppSearchResultParcel resultParcel) {
- executor.execute(() -> {
- AppSearchResult<Void> result = resultParcel.getResult();
- if (result.isSuccess()) {
- callback.accept(
- AppSearchResult.newSuccessfulResult(GlobalSearchSession.this));
- } else {
- callback.accept(AppSearchResult.newFailedResult(result));
- }
+ mService.initialize(mUserId,
+ /*binderCallStartTimeMillis=*/ SystemClock.elapsedRealtime(),
+ new IAppSearchResultCallback.Stub() {
+ @Override
+ public void onResult(AppSearchResultParcel resultParcel) {
+ executor.execute(() -> {
+ AppSearchResult<Void> result = resultParcel.getResult();
+ if (result.isSuccess()) {
+ callback.accept(
+ AppSearchResult.newSuccessfulResult(
+ GlobalSearchSession.this));
+ } else {
+ callback.accept(AppSearchResult.newFailedResult(result));
+ }
});
}
});
@@ -182,7 +186,8 @@
public void close() {
if (mIsMutated && !mIsClosed) {
try {
- mService.persistToDisk(mUserId);
+ mService.persistToDisk(mUserId,
+ /*binderCallStartTimeMillis=*/ SystemClock.elapsedRealtime());
mIsClosed = true;
} catch (RemoteException e) {
Log.e(TAG, "Unable to close the GlobalSearchSession", e);
diff --git a/apex/appsearch/framework/java/android/app/appsearch/SearchResults.java b/apex/appsearch/framework/java/android/app/appsearch/SearchResults.java
index 4368672..0106b0f 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/SearchResults.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/SearchResults.java
@@ -25,6 +25,7 @@
import android.app.appsearch.aidl.IAppSearchResultCallback;
import android.os.Bundle;
import android.os.RemoteException;
+import android.os.SystemClock;
import android.util.Log;
import com.android.internal.util.Preconditions;
@@ -109,14 +110,19 @@
try {
if (mIsFirstLoad) {
mIsFirstLoad = false;
+ long binderCallStartTimeMillis = SystemClock.elapsedRealtime();
if (mDatabaseName == null) {
// Global query, there's no one package-database combination to check.
mService.globalQuery(mPackageName, mQueryExpression,
- mSearchSpec.getBundle(), mUserId, wrapCallback(executor, callback));
+ mSearchSpec.getBundle(), mUserId,
+ binderCallStartTimeMillis,
+ wrapCallback(executor, callback));
} else {
// Normal local query, pass in specified database.
mService.query(mPackageName, mDatabaseName, mQueryExpression,
- mSearchSpec.getBundle(), mUserId, wrapCallback(executor, callback));
+ mSearchSpec.getBundle(), mUserId,
+ binderCallStartTimeMillis,
+ wrapCallback(executor, callback));
}
} else {
mService.getNextPage(mNextPageToken, mUserId, wrapCallback(executor, callback));
diff --git a/apex/appsearch/framework/java/android/app/appsearch/aidl/IAppSearchManager.aidl b/apex/appsearch/framework/java/android/app/appsearch/aidl/IAppSearchManager.aidl
index 6f7e82e..18ebddc 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/aidl/IAppSearchManager.aidl
+++ b/apex/appsearch/framework/java/android/app/appsearch/aidl/IAppSearchManager.aidl
@@ -37,6 +37,7 @@
* incompatible documents will be deleted.
* @param schemaVersion The overall schema version number of the request.
* @param userId Id of the calling user
+ * @param binderCallStartTimeMillis start timestamp of binder call in Millis
* @param callback {@link IAppSearchResultCallback#onResult} will be called with an
* {@link AppSearchResult}<{@link Bundle}>, where the value are
* {@link SetSchemaResponse} bundle.
@@ -50,6 +51,7 @@
boolean forceOverride,
in int schemaVersion,
in int userId,
+ in long binderCallStartTimeMillis,
in IAppSearchResultCallback callback);
/**
@@ -115,6 +117,7 @@
* @param typePropertyPaths A map of schema type to a list of property paths to return in the
* result.
* @param userId Id of the calling user
+ * @param binderCallStartTimeMillis start timestamp of binder call in Millis
* @param callback
* If the call fails to start, {@link IAppSearchBatchResultCallback#onSystemError}
* will be called with the cause throwable. Otherwise,
@@ -129,6 +132,7 @@
in List<String> ids,
in Map<String, List<String>> typePropertyPaths,
in int userId,
+ in long binderCallStartTimeMillis,
in IAppSearchBatchResultCallback callback);
/**
@@ -139,6 +143,7 @@
* @param queryExpression String to search for
* @param searchSpecBundle SearchSpec bundle
* @param userId Id of the calling user
+ * @param binderCallStartTimeMillis start timestamp of binder call in Millis
* @param callback {@link AppSearchResult}<{@link Bundle}> of performing this
* operation.
*/
@@ -148,6 +153,7 @@
in String queryExpression,
in Bundle searchSpecBundle,
in int userId,
+ in long binderCallStartTimeMillis,
in IAppSearchResultCallback callback);
/**
@@ -158,6 +164,7 @@
* @param queryExpression String to search for
* @param searchSpecBundle SearchSpec bundle
* @param userId Id of the calling user
+ * @param binderCallStartTimeMillis start timestamp of binder call in Millis
* @param callback {@link AppSearchResult}<{@link Bundle}> of performing this
* operation.
*/
@@ -166,6 +173,7 @@
in String queryExpression,
in Bundle searchSpecBundle,
in int userId,
+ in long binderCallStartTimeMillis,
in IAppSearchResultCallback callback);
/**
@@ -269,6 +277,7 @@
* @param namespace Namespace of the document to remove.
* @param ids The IDs of the documents to delete
* @param userId Id of the calling user
+ * @param binderCallStartTimeMillis start timestamp of binder call in Millis
* @param callback
* If the call fails to start, {@link IAppSearchBatchResultCallback#onSystemError}
* will be called with the cause throwable. Otherwise,
@@ -283,6 +292,7 @@
in String namespace,
in List<String> ids,
in int userId,
+ in long binderCallStartTimeMillis,
in IAppSearchBatchResultCallback callback);
/**
@@ -293,6 +303,7 @@
* @param queryExpression String to search for
* @param searchSpecBundle SearchSpec bundle
* @param userId Id of the calling user
+ * @param binderCallStartTimeMillis start timestamp of binder call in Millis
* @param callback {@link IAppSearchResultCallback#onResult} will be called with an
* {@link AppSearchResult}<{@link Void}>.
*/
@@ -302,6 +313,7 @@
in String queryExpression,
in Bundle searchSpecBundle,
in int userId,
+ in long binderCallStartTimeMillis,
in IAppSearchResultCallback callback);
/**
@@ -324,15 +336,20 @@
* Persists all update/delete requests to the disk.
*
* @param userId Id of the calling user
+ * @param binderCallStartTimeMillis start timestamp of binder call in Millis
*/
- void persistToDisk(in int userId);
+ void persistToDisk(in int userId, in long binderCallStartTimeMillis);
/**
* Creates and initializes AppSearchImpl for the calling app.
*
* @param userId Id of the calling user
+ * @param binderCallStartTimeMillis start timestamp of binder call in Millis
* @param callback {@link IAppSearchResultCallback#onResult} will be called with an
* {@link AppSearchResult}<{@link Void}>.
*/
- void initialize(in int userId, in IAppSearchResultCallback callback);
+ void initialize(
+ in int userId,
+ in long binderCallStartTimeMillis,
+ in IAppSearchResultCallback callback);
}
diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/AppSearchBatchResult.java b/apex/appsearch/framework/java/external/android/app/appsearch/AppSearchBatchResult.java
index f0b04fc..272e12d 100644
--- a/apex/appsearch/framework/java/external/android/app/appsearch/AppSearchBatchResult.java
+++ b/apex/appsearch/framework/java/external/android/app/appsearch/AppSearchBatchResult.java
@@ -19,6 +19,7 @@
import android.annotation.Nullable;
import android.util.ArrayMap;
+import java.util.Collections;
import java.util.Map;
import java.util.Objects;
@@ -48,9 +49,9 @@
@NonNull Map<KeyType, ValueType> successes,
@NonNull Map<KeyType, AppSearchResult<ValueType>> failures,
@NonNull Map<KeyType, AppSearchResult<ValueType>> all) {
- mSuccesses = successes;
- mFailures = failures;
- mAll = all;
+ mSuccesses = Objects.requireNonNull(successes);
+ mFailures = Objects.requireNonNull(failures);
+ mAll = Objects.requireNonNull(all);
}
/** Returns {@code true} if this {@link AppSearchBatchResult} has no failures. */
@@ -70,7 +71,7 @@
*/
@NonNull
public Map<KeyType, ValueType> getSuccesses() {
- return mSuccesses;
+ return Collections.unmodifiableMap(mSuccesses);
}
/**
@@ -81,7 +82,7 @@
*/
@NonNull
public Map<KeyType, AppSearchResult<ValueType>> getFailures() {
- return mFailures;
+ return Collections.unmodifiableMap(mFailures);
}
/**
@@ -92,7 +93,7 @@
*/
@NonNull
public Map<KeyType, AppSearchResult<ValueType>> getAll() {
- return mAll;
+ return Collections.unmodifiableMap(mAll);
}
/**
@@ -128,20 +129,37 @@
* Associates the {@code key} with the provided successful return value.
*
* <p>Any previous mapping for a key, whether success or failure, is deleted.
+ *
+ * <p>This is a convenience function which is equivalent to {@code setResult(key,
+ * AppSearchResult.newSuccessfulResult(value))}.
+ *
+ * @param key The key to associate the result with; usually corresponds to some identifier
+ * from the input like an ID or name.
+ * @param value An optional value to associate with the successful result of the operation
+ * being performed.
*/
@SuppressWarnings("MissingGetterMatchingBuilder") // See getSuccesses
@NonNull
public Builder<KeyType, ValueType> setSuccess(
- @NonNull KeyType key, @Nullable ValueType result) {
+ @NonNull KeyType key, @Nullable ValueType value) {
Objects.requireNonNull(key);
resetIfBuilt();
- return setResult(key, AppSearchResult.newSuccessfulResult(result));
+ return setResult(key, AppSearchResult.newSuccessfulResult(value));
}
/**
* Associates the {@code key} with the provided failure code and error message.
*
* <p>Any previous mapping for a key, whether success or failure, is deleted.
+ *
+ * <p>This is a convenience function which is equivalent to {@code setResult(key,
+ * AppSearchResult.newFailedResult(resultCode, errorMessage))}.
+ *
+ * @param key The key to associate the result with; usually corresponds to some identifier
+ * from the input like an ID or name.
+ * @param resultCode One of the constants documented in {@link
+ * AppSearchResult#getResultCode}.
+ * @param errorMessage An optional string describing the reason or nature of the failure.
*/
@SuppressWarnings("MissingGetterMatchingBuilder") // See getFailures
@NonNull
@@ -158,6 +176,10 @@
* Associates the {@code key} with the provided {@code result}.
*
* <p>Any previous mapping for a key, whether success or failure, is deleted.
+ *
+ * @param key The key to associate the result with; usually corresponds to some identifier
+ * from the input like an ID or name.
+ * @param result The result to associate with the key.
*/
@SuppressWarnings("MissingGetterMatchingBuilder") // See getAll
@NonNull
@@ -183,8 +205,7 @@
@NonNull
public AppSearchBatchResult<KeyType, ValueType> build() {
mBuilt = true;
- return new AppSearchBatchResult<>(
- new ArrayMap<>(mSuccesses), new ArrayMap<>(mFailures), new ArrayMap<>(mAll));
+ return new AppSearchBatchResult<>(mSuccesses, mFailures, mAll);
}
private void resetIfBuilt() {
diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/AppSearchResult.java b/apex/appsearch/framework/java/external/android/app/appsearch/AppSearchResult.java
index 30c98b0..c57cf2e 100644
--- a/apex/appsearch/framework/java/external/android/app/appsearch/AppSearchResult.java
+++ b/apex/appsearch/framework/java/external/android/app/appsearch/AppSearchResult.java
@@ -175,14 +175,24 @@
return "[FAILURE(" + mResultCode + ")]: " + mErrorMessage;
}
- /** Creates a new successful {@link AppSearchResult}. */
+ /**
+ * Creates a new successful {@link AppSearchResult}.
+ *
+ * @param value An optional value to associate with the successful result of the operation being
+ * performed.
+ */
@NonNull
public static <ValueType> AppSearchResult<ValueType> newSuccessfulResult(
@Nullable ValueType value) {
return new AppSearchResult<>(RESULT_OK, value, /*errorMessage=*/ null);
}
- /** Creates a new failed {@link AppSearchResult}. */
+ /**
+ * Creates a new failed {@link AppSearchResult}.
+ *
+ * @param resultCode One of the constants documented in {@link AppSearchResult#getResultCode}.
+ * @param errorMessage An optional string describing the reason or nature of the failure.
+ */
@NonNull
public static <ValueType> AppSearchResult<ValueType> newFailedResult(
@ResultCode int resultCode, @Nullable String errorMessage) {
diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/AppSearchSchema.java b/apex/appsearch/framework/java/external/android/app/appsearch/AppSearchSchema.java
index c1fcd6c..3619a56 100644
--- a/apex/appsearch/framework/java/external/android/app/appsearch/AppSearchSchema.java
+++ b/apex/appsearch/framework/java/external/android/app/appsearch/AppSearchSchema.java
@@ -182,7 +182,7 @@
@IntDef(
value = {
DATA_TYPE_STRING,
- DATA_TYPE_INT64,
+ DATA_TYPE_LONG,
DATA_TYPE_DOUBLE,
DATA_TYPE_BOOLEAN,
DATA_TYPE_BYTES,
@@ -195,7 +195,7 @@
public static final int DATA_TYPE_STRING = 1;
/** @hide */
- public static final int DATA_TYPE_INT64 = 2;
+ public static final int DATA_TYPE_LONG = 2;
/** @hide */
public static final int DATA_TYPE_DOUBLE = 3;
@@ -315,8 +315,8 @@
switch (propertyBundle.getInt(PropertyConfig.DATA_TYPE_FIELD)) {
case PropertyConfig.DATA_TYPE_STRING:
return new StringPropertyConfig(propertyBundle);
- case PropertyConfig.DATA_TYPE_INT64:
- return new Int64PropertyConfig(propertyBundle);
+ case PropertyConfig.DATA_TYPE_LONG:
+ return new LongPropertyConfig(propertyBundle);
case PropertyConfig.DATA_TYPE_DOUBLE:
return new DoublePropertyConfig(propertyBundle);
case PropertyConfig.DATA_TYPE_BOOLEAN:
@@ -485,8 +485,13 @@
}
}
- /** Configuration for a property containing a 64-bit integer. */
- public static final class Int64PropertyConfig extends PropertyConfig {
+ /**
+ * @deprecated TODO(b/181887768): Exists for dogfood transition; must be removed.
+ * @hide
+ */
+ @Deprecated
+ @UnsupportedAppUsage(implicitMember = "")
+ public static class Int64PropertyConfig extends PropertyConfig {
Int64PropertyConfig(@NonNull Bundle bundle) {
super(bundle);
}
@@ -497,6 +502,7 @@
private @Cardinality int mCardinality = CARDINALITY_OPTIONAL;
/** Creates a new {@link Int64PropertyConfig.Builder}. */
+ @UnsupportedAppUsage
public Builder(@NonNull String propertyName) {
mPropertyName = Objects.requireNonNull(propertyName);
}
@@ -509,6 +515,7 @@
*/
@SuppressWarnings("MissingGetterMatchingBuilder") // getter defined in superclass
@NonNull
+ @UnsupportedAppUsage
public Int64PropertyConfig.Builder setCardinality(@Cardinality int cardinality) {
Preconditions.checkArgumentInRange(
cardinality, CARDINALITY_REPEATED, CARDINALITY_REQUIRED, "cardinality");
@@ -518,16 +525,61 @@
/** Constructs a new {@link Int64PropertyConfig} from the contents of this builder. */
@NonNull
+ @UnsupportedAppUsage
public Int64PropertyConfig build() {
Bundle bundle = new Bundle();
bundle.putString(NAME_FIELD, mPropertyName);
- bundle.putInt(DATA_TYPE_FIELD, DATA_TYPE_INT64);
+ bundle.putInt(DATA_TYPE_FIELD, DATA_TYPE_LONG);
bundle.putInt(CARDINALITY_FIELD, mCardinality);
return new Int64PropertyConfig(bundle);
}
}
}
+ /** Configuration for a property containing a 64-bit integer. */
+ // TODO(b/181887768): This should extend directly from PropertyConfig
+ public static final class LongPropertyConfig extends Int64PropertyConfig {
+ LongPropertyConfig(@NonNull Bundle bundle) {
+ super(bundle);
+ }
+
+ /** Builder for {@link LongPropertyConfig}. */
+ public static final class Builder {
+ private final String mPropertyName;
+ private @Cardinality int mCardinality = CARDINALITY_OPTIONAL;
+
+ /** Creates a new {@link LongPropertyConfig.Builder}. */
+ public Builder(@NonNull String propertyName) {
+ mPropertyName = Objects.requireNonNull(propertyName);
+ }
+
+ /**
+ * The cardinality of the property (whether it is optional, required or repeated).
+ *
+ * <p>If this method is not called, the default cardinality is {@link
+ * PropertyConfig#CARDINALITY_OPTIONAL}.
+ */
+ @SuppressWarnings("MissingGetterMatchingBuilder") // getter defined in superclass
+ @NonNull
+ public LongPropertyConfig.Builder setCardinality(@Cardinality int cardinality) {
+ Preconditions.checkArgumentInRange(
+ cardinality, CARDINALITY_REPEATED, CARDINALITY_REQUIRED, "cardinality");
+ mCardinality = cardinality;
+ return this;
+ }
+
+ /** Constructs a new {@link LongPropertyConfig} from the contents of this builder. */
+ @NonNull
+ public LongPropertyConfig build() {
+ Bundle bundle = new Bundle();
+ bundle.putString(NAME_FIELD, mPropertyName);
+ bundle.putInt(DATA_TYPE_FIELD, DATA_TYPE_LONG);
+ bundle.putInt(CARDINALITY_FIELD, mCardinality);
+ return new LongPropertyConfig(bundle);
+ }
+ }
+ }
+
/** Configuration for a property containing a double-precision decimal number. */
public static final class DoublePropertyConfig extends PropertyConfig {
DoublePropertyConfig(@NonNull Bundle bundle) {
diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/GetByDocumentIdRequest.java b/apex/appsearch/framework/java/external/android/app/appsearch/GetByDocumentIdRequest.java
index e324b9f..558899e 100644
--- a/apex/appsearch/framework/java/external/android/app/appsearch/GetByDocumentIdRequest.java
+++ b/apex/appsearch/framework/java/external/android/app/appsearch/GetByDocumentIdRequest.java
@@ -164,8 +164,7 @@
@NonNull
public GetByDocumentIdRequest build() {
mBuilt = true;
- return new GetByDocumentIdRequest(
- mNamespace, new ArraySet<>(mIds), new ArrayMap<>(mProjectionTypePropertyPaths));
+ return new GetByDocumentIdRequest(mNamespace, mIds, mProjectionTypePropertyPaths);
}
private void resetIfBuilt() {
diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/ReportSystemUsageRequest.java b/apex/appsearch/framework/java/external/android/app/appsearch/ReportSystemUsageRequest.java
index b6575c2..26bdf03 100644
--- a/apex/appsearch/framework/java/external/android/app/appsearch/ReportSystemUsageRequest.java
+++ b/apex/appsearch/framework/java/external/android/app/appsearch/ReportSystemUsageRequest.java
@@ -93,14 +93,25 @@
private final String mDocumentId;
private Long mUsageTimestampMillis;
- /** Creates a {@link ReportSystemUsageRequest.Builder} instance. */
+ /**
+ * Creates a {@link ReportSystemUsageRequest.Builder} instance.
+ *
+ * @param packageName The package name of the app which owns the document that was used
+ * (e.g. from {@link SearchResult#getPackageName}).
+ * @param databaseName The database in which the document that was used resides (e.g. from
+ * {@link SearchResult#getDatabaseName}).
+ * @param namespace The namespace of the document that was used (e.g. from {@link
+ * GenericDocument#getNamespace}.
+ * @param documentId The ID of document that was used (e.g. from {@link
+ * GenericDocument#getId}.
+ */
public Builder(
@NonNull String packageName,
- @NonNull String database,
+ @NonNull String databaseName,
@NonNull String namespace,
@NonNull String documentId) {
mPackageName = Objects.requireNonNull(packageName);
- mDatabase = Objects.requireNonNull(database);
+ mDatabase = Objects.requireNonNull(databaseName);
mNamespace = Objects.requireNonNull(namespace);
mDocumentId = Objects.requireNonNull(documentId);
}
diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/ReportUsageRequest.java b/apex/appsearch/framework/java/external/android/app/appsearch/ReportUsageRequest.java
index 59fa6e0..c388bde 100644
--- a/apex/appsearch/framework/java/external/android/app/appsearch/ReportUsageRequest.java
+++ b/apex/appsearch/framework/java/external/android/app/appsearch/ReportUsageRequest.java
@@ -71,7 +71,14 @@
private String mDocumentId;
private Long mUsageTimestampMillis;
- /** Creates a {@link ReportUsageRequest.Builder} instance. */
+ /**
+ * Creates a new {@link ReportUsageRequest.Builder} instance.
+ *
+ * @param namespace The namespace of the document that was used (e.g. from {@link
+ * GenericDocument#getNamespace}.
+ * @param documentId The ID of document that was used (e.g. from {@link
+ * GenericDocument#getId}.
+ */
public Builder(@NonNull String namespace, @NonNull String documentId) {
mNamespace = Objects.requireNonNull(namespace);
mDocumentId = Objects.requireNonNull(documentId);
diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/SetSchemaResponse.java b/apex/appsearch/framework/java/external/android/app/appsearch/SetSchemaResponse.java
index 2c75b71..3e5a2ca 100644
--- a/apex/appsearch/framework/java/external/android/app/appsearch/SetSchemaResponse.java
+++ b/apex/appsearch/framework/java/external/android/app/appsearch/SetSchemaResponse.java
@@ -375,5 +375,19 @@
mBundle.getInt(RESULT_CODE_FIELD),
mBundle.getString(ERROR_MESSAGE_FIELD, /*defaultValue=*/ ""));
}
+
+ @NonNull
+ @Override
+ public String toString() {
+ return "MigrationFailure { schemaType: "
+ + getSchemaType()
+ + ", namespace: "
+ + getNamespace()
+ + ", documentId: "
+ + getDocumentId()
+ + ", appSearchResult: "
+ + getAppSearchResult().toString()
+ + "}";
+ }
}
}
diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/util/LogUtil.java b/apex/appsearch/framework/java/external/android/app/appsearch/util/LogUtil.java
new file mode 100644
index 0000000..f2cc3b9
--- /dev/null
+++ b/apex/appsearch/framework/java/external/android/app/appsearch/util/LogUtil.java
@@ -0,0 +1,104 @@
+/*
+ * 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 android.app.appsearch.util;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.util.Log;
+
+import java.util.Objects;
+
+/**
+ * Utilities for logging to logcat.
+ *
+ * @hide
+ */
+public final class LogUtil {
+ /**
+ * The {@link #piiTrace} logs are intended for sensitive data that can't be enabled in
+ * production, so they are build-gated by this constant.
+ *
+ * <p>
+ *
+ * <ul>
+ * <li>0: no tracing.
+ * <li>1: fast tracing (statuses/counts only)
+ * <li>2: full tracing (complete messages)
+ * </ul>
+ */
+ private static final int PII_TRACE_LEVEL = 0;
+
+ private final String mTag;
+
+ public LogUtil(@NonNull String tag) {
+ mTag = Objects.requireNonNull(tag);
+ }
+
+ /** Returns whether piiTrace() is enabled (PII_TRACE_LEVEL > 0). */
+ public boolean isPiiTraceEnabled() {
+ return PII_TRACE_LEVEL > 0;
+ }
+
+ /**
+ * If icing lib interaction tracing is enabled via {@link #PII_TRACE_LEVEL}, logs the provided
+ * message to logcat.
+ *
+ * <p>If {@link #PII_TRACE_LEVEL} is 0, nothing is logged and this method returns immediately.
+ */
+ public void piiTrace(@NonNull String message) {
+ piiTrace(message, /*fastTraceObj=*/ null, /*fullTraceObj=*/ null);
+ }
+
+ /**
+ * If icing lib interaction tracing is enabled via {@link #PII_TRACE_LEVEL}, logs the provided
+ * message and object to logcat.
+ *
+ * <p>If {@link #PII_TRACE_LEVEL} is 0, nothing is logged and this method returns immediately.
+ *
+ * <p>Otherwise, {@code traceObj} is logged if it is non-null.
+ */
+ public void piiTrace(@NonNull String message, @Nullable Object traceObj) {
+ piiTrace(message, /*fastTraceObj=*/ traceObj, /*fullTraceObj=*/ null);
+ }
+
+ /**
+ * If icing lib interaction tracing is enabled via {@link #PII_TRACE_LEVEL}, logs the provided
+ * message and objects to logcat.
+ *
+ * <p>If {@link #PII_TRACE_LEVEL} is 0, nothing is logged and this method returns immediately.
+ *
+ * <p>If {@link #PII_TRACE_LEVEL} is 1, {@code fastTraceObj} is logged if it is non-null.
+ *
+ * <p>If {@link #PII_TRACE_LEVEL} is 2, {@code fullTraceObj} is logged if it is non-null, else
+ * {@code fastTraceObj} is logged if it is non-null..
+ */
+ public void piiTrace(
+ @NonNull String message, @Nullable Object fastTraceObj, @Nullable Object fullTraceObj) {
+ if (PII_TRACE_LEVEL == 0) {
+ return;
+ }
+ StringBuilder builder = new StringBuilder("(trace) ").append(message);
+ if (PII_TRACE_LEVEL == 1 && fastTraceObj != null) {
+ builder.append(": ").append(fastTraceObj);
+ } else if (PII_TRACE_LEVEL == 2 && fullTraceObj != null) {
+ builder.append(": ").append(fullTraceObj);
+ } else if (PII_TRACE_LEVEL == 2 && fastTraceObj != null) {
+ builder.append(": ").append(fastTraceObj);
+ }
+ Log.i(mTag, builder.toString());
+ }
+}
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 777f9fe..61ac63e 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
@@ -217,10 +217,13 @@
}
if (ImplInstanceManager.getAppSearchDir(userId).exists()) {
// Only clear the package's data if AppSearch exists for this user.
- AppSearchImpl impl = mImplInstanceManager.getOrCreateAppSearchImpl(mContext,
+ PlatformLogger logger = mLoggerInstanceManager.getOrCreatePlatformLogger(mContext,
userId);
+ AppSearchImpl impl = mImplInstanceManager.getOrCreateAppSearchImpl(mContext,
+ userId, logger);
//TODO(b/145759910) clear visibility setting for package.
impl.clearPackageData(packageName);
+ logger.removeCachedUidForPackage(packageName);
}
} catch (Throwable t) {
Log.e(TAG, "Unable to remove data for package: " + packageName, t);
@@ -275,14 +278,20 @@
boolean forceOverride,
int schemaVersion,
@UserIdInt int userId,
+ @ElapsedRealtimeLong long binderCallStartTimeMillis,
@NonNull IAppSearchResultCallback callback) {
Objects.requireNonNull(packageName);
Objects.requireNonNull(databaseName);
Objects.requireNonNull(schemaBundles);
Objects.requireNonNull(callback);
+ long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
int callingUid = Binder.getCallingUid();
int callingUserId = handleIncomingUser(userId, callingUid);
EXECUTOR.execute(() -> {
+ @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
+ PlatformLogger logger = null;
+ int operationSuccessCount = 0;
+ int operationFailureCount = 0;
try {
verifyUserUnlocked(callingUserId);
verifyCallingPackage(callingUid, packageName);
@@ -303,6 +312,7 @@
schemasPackageAccessible.put(entry.getKey(), packageIdentifiers);
}
AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUserId);
+ logger = mLoggerInstanceManager.getPlatformLogger(callingUserId);
SetSchemaResponse setSchemaResponse = impl.setSchema(
packageName,
databaseName,
@@ -311,10 +321,33 @@
schemasPackageAccessible,
forceOverride,
schemaVersion);
+ ++operationSuccessCount;
invokeCallbackOnResult(callback,
AppSearchResult.newSuccessfulResult(setSchemaResponse.getBundle()));
} catch (Throwable t) {
+ ++operationFailureCount;
+ statusCode = throwableToFailedResult(t).getResultCode();
invokeCallbackOnError(callback, t);
+ } finally {
+ if (logger != null) {
+ int estimatedBinderLatencyMillis =
+ 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
+ int totalLatencyMillis =
+ (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
+ CallStats.Builder cBuilder = new CallStats.Builder(packageName,
+ databaseName)
+ .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());
+ }
}
});
}
@@ -384,10 +417,10 @@
Objects.requireNonNull(databaseName);
Objects.requireNonNull(documentBundles);
Objects.requireNonNull(callback);
+ long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
int callingUid = Binder.getCallingUid();
int callingUserId = handleIncomingUser(userId, callingUid);
EXECUTOR.execute(() -> {
- long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
@AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
PlatformLogger logger = null;
int operationSuccessCount = 0;
@@ -411,7 +444,8 @@
throwableToFailedResult(t));
AppSearchResult<Void> result = throwableToFailedResult(t);
resultBuilder.setResult(document.getId(), result);
- // for failures, we would just log the one for last failure
+ // Since we can only include one status code in the atom,
+ // for failures, we would just save the one for the last failure
statusCode = result.getResultCode();
++operationFailureCount;
}
@@ -420,25 +454,27 @@
impl.persistToDisk(PersistType.Code.LITE);
invokeCallbackOnResult(callback, resultBuilder.build());
} catch (Throwable t) {
+ ++operationFailureCount;
+ statusCode = throwableToFailedResult(t).getResultCode();
invokeCallbackOnError(callback, t);
} finally {
if (logger != null) {
+ int estimatedBinderLatencyMillis =
+ 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
+ int totalLatencyMillis =
+ (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
CallStats.Builder cBuilder = new CallStats.Builder(packageName,
databaseName)
.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(
- 2 * (int) (totalLatencyStartTimeMillis
- - binderCallStartTimeMillis))
+ .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
.setNumOperationsSucceeded(operationSuccessCount)
.setNumOperationsFailed(operationFailureCount);
cBuilder.getGeneralStatsBuilder()
.setStatusCode(statusCode)
- .setTotalLatencyMillis(
- (int) (SystemClock.elapsedRealtime()
- - totalLatencyStartTimeMillis));
+ .setTotalLatencyMillis(totalLatencyMillis);
logger.logStats(cBuilder.build());
}
}
@@ -453,15 +489,21 @@
@NonNull List<String> ids,
@NonNull Map<String, List<String>> typePropertyPaths,
@UserIdInt int userId,
+ @ElapsedRealtimeLong long binderCallStartTimeMillis,
@NonNull IAppSearchBatchResultCallback callback) {
Objects.requireNonNull(packageName);
Objects.requireNonNull(databaseName);
Objects.requireNonNull(namespace);
Objects.requireNonNull(ids);
Objects.requireNonNull(callback);
+ long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
int callingUid = Binder.getCallingUid();
int callingUserId = handleIncomingUser(userId, callingUid);
EXECUTOR.execute(() -> {
+ @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
+ PlatformLogger logger = null;
+ int operationSuccessCount = 0;
+ int operationFailureCount = 0;
try {
verifyUserUnlocked(callingUserId);
verifyCallingPackage(callingUid, packageName);
@@ -469,6 +511,7 @@
new AppSearchBatchResult.Builder<>();
AppSearchImpl impl =
mImplInstanceManager.getAppSearchImpl(callingUserId);
+ logger = mLoggerInstanceManager.getPlatformLogger(callingUserId);
for (int i = 0; i < ids.size(); i++) {
String id = ids.get(i);
try {
@@ -479,14 +522,42 @@
namespace,
id,
typePropertyPaths);
+ ++operationSuccessCount;
resultBuilder.setSuccess(id, document.getBundle());
} catch (Throwable t) {
- resultBuilder.setResult(id, throwableToFailedResult(t));
+ // Since we can only include one status code in the atom,
+ // for failures, we would just save the one for the last failure
+ AppSearchResult<Bundle> result = throwableToFailedResult(t);
+ resultBuilder.setResult(id, result);
+ statusCode = result.getResultCode();
+ ++operationFailureCount;
}
}
invokeCallbackOnResult(callback, resultBuilder.build());
} catch (Throwable t) {
+ ++operationFailureCount;
+ statusCode = throwableToFailedResult(t).getResultCode();
invokeCallbackOnError(callback, t);
+ } finally {
+ if (logger != null) {
+ int estimatedBinderLatencyMillis =
+ 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
+ int totalLatencyMillis =
+ (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
+ CallStats.Builder cBuilder = new CallStats.Builder(packageName,
+ databaseName)
+ .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());
+ }
}
});
}
@@ -498,32 +569,62 @@
@NonNull String queryExpression,
@NonNull Bundle searchSpecBundle,
@UserIdInt int userId,
+ @ElapsedRealtimeLong long binderCallStartTimeMillis,
@NonNull IAppSearchResultCallback callback) {
Objects.requireNonNull(packageName);
Objects.requireNonNull(databaseName);
Objects.requireNonNull(queryExpression);
Objects.requireNonNull(searchSpecBundle);
Objects.requireNonNull(callback);
+ long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
int callingUid = Binder.getCallingUid();
int callingUserId = handleIncomingUser(userId, callingUid);
EXECUTOR.execute(() -> {
+ @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
+ PlatformLogger logger = null;
+ int operationSuccessCount = 0;
+ int operationFailureCount = 0;
try {
verifyUserUnlocked(callingUserId);
verifyCallingPackage(callingUid, packageName);
AppSearchImpl impl =
mImplInstanceManager.getAppSearchImpl(callingUserId);
+ logger = mLoggerInstanceManager.getPlatformLogger(callingUserId);
SearchResultPage searchResultPage =
impl.query(
packageName,
databaseName,
queryExpression,
new SearchSpec(searchSpecBundle),
- /*logger=*/ null);
+ logger);
+ ++operationSuccessCount;
invokeCallbackOnResult(
callback,
AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
} catch (Throwable t) {
+ ++operationFailureCount;
+ statusCode = throwableToFailedResult(t).getResultCode();
invokeCallbackOnError(callback, t);
+ } finally {
+ if (logger != null) {
+ int estimatedBinderLatencyMillis =
+ 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
+ int totalLatencyMillis =
+ (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
+ CallStats.Builder cBuilder = new CallStats.Builder(packageName,
+ databaseName)
+ .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());
+ }
}
});
}
@@ -534,17 +635,24 @@
@NonNull String queryExpression,
@NonNull Bundle searchSpecBundle,
@UserIdInt int userId,
+ @ElapsedRealtimeLong long binderCallStartTimeMillis,
@NonNull IAppSearchResultCallback callback) {
Objects.requireNonNull(packageName);
Objects.requireNonNull(queryExpression);
Objects.requireNonNull(searchSpecBundle);
Objects.requireNonNull(callback);
+ long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
int callingUid = Binder.getCallingUid();
int callingUserId = handleIncomingUser(userId, callingUid);
EXECUTOR.execute(() -> {
+ @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
+ PlatformLogger logger = null;
+ int operationSuccessCount = 0;
+ int operationFailureCount = 0;
try {
verifyUserUnlocked(callingUserId);
verifyCallingPackage(callingUid, packageName);
+ logger = mLoggerInstanceManager.getPlatformLogger(callingUserId);
AppSearchImpl impl =
mImplInstanceManager.getAppSearchImpl(callingUserId);
SearchResultPage searchResultPage =
@@ -553,12 +661,36 @@
new SearchSpec(searchSpecBundle),
packageName,
callingUid,
- /*logger=*/ null);
+ logger);
+ ++operationSuccessCount;
invokeCallbackOnResult(
callback,
AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
- } catch (Throwable t) {
+ } catch (Throwable t) {
+ ++operationFailureCount;
+ statusCode = throwableToFailedResult(t).getResultCode();
invokeCallbackOnError(callback, t);
+ } finally {
+ if (logger != null) {
+ int estimatedBinderLatencyMillis =
+ 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=*/ "")
+ .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());
+ }
}
});
}
@@ -739,14 +871,20 @@
@NonNull String namespace,
@NonNull List<String> ids,
@UserIdInt int userId,
+ @ElapsedRealtimeLong long binderCallStartTimeMillis,
@NonNull IAppSearchBatchResultCallback callback) {
Objects.requireNonNull(packageName);
Objects.requireNonNull(databaseName);
Objects.requireNonNull(ids);
Objects.requireNonNull(callback);
+ long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
int callingUid = Binder.getCallingUid();
int callingUserId = handleIncomingUser(userId, callingUid);
EXECUTOR.execute(() -> {
+ @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
+ PlatformLogger logger = null;
+ int operationSuccessCount = 0;
+ int operationFailureCount = 0;
try {
verifyUserUnlocked(callingUserId);
verifyCallingPackage(callingUid, packageName);
@@ -754,20 +892,49 @@
new AppSearchBatchResult.Builder<>();
AppSearchImpl impl =
mImplInstanceManager.getAppSearchImpl(callingUserId);
+ logger = mLoggerInstanceManager.getPlatformLogger(callingUserId);
for (int i = 0; i < ids.size(); i++) {
String id = ids.get(i);
try {
impl.remove(packageName, databaseName, namespace, id);
+ ++operationSuccessCount;
resultBuilder.setSuccess(id, /*result= */ null);
} catch (Throwable t) {
- resultBuilder.setResult(id, throwableToFailedResult(t));
+ AppSearchResult<Void> result = throwableToFailedResult(t);
+ resultBuilder.setResult(id, result);
+ // Since we can only include one status code in the atom,
+ // for failures, we would just save the one for the last failure
+ statusCode = result.getResultCode();
+ ++operationFailureCount;
}
}
// Now that the batch has been written. Persist the newly written data.
impl.persistToDisk(PersistType.Code.LITE);
invokeCallbackOnResult(callback, resultBuilder.build());
} catch (Throwable t) {
+ ++operationFailureCount;
+ statusCode = throwableToFailedResult(t).getResultCode();
invokeCallbackOnError(callback, t);
+ } finally {
+ if (logger != null) {
+ int estimatedBinderLatencyMillis =
+ 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
+ int totalLatencyMillis =
+ (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
+ CallStats.Builder cBuilder = new CallStats.Builder(packageName,
+ databaseName)
+ .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());
+ }
}
});
}
@@ -779,20 +946,28 @@
@NonNull String queryExpression,
@NonNull Bundle searchSpecBundle,
@UserIdInt int userId,
+ @ElapsedRealtimeLong long binderCallStartTimeMillis,
@NonNull IAppSearchResultCallback callback) {
+ // TODO(b/173532925) log CallStats once we have CALL_TYPE_REMOVE_BY_QUERY added
Objects.requireNonNull(packageName);
Objects.requireNonNull(databaseName);
Objects.requireNonNull(queryExpression);
Objects.requireNonNull(searchSpecBundle);
Objects.requireNonNull(callback);
+ long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
int callingUid = Binder.getCallingUid();
int callingUserId = handleIncomingUser(userId, callingUid);
EXECUTOR.execute(() -> {
+ @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
+ PlatformLogger logger = null;
+ int operationSuccessCount = 0;
+ int operationFailureCount = 0;
try {
verifyUserUnlocked(callingUserId);
verifyCallingPackage(callingUid, packageName);
AppSearchImpl impl =
mImplInstanceManager.getAppSearchImpl(callingUserId);
+ logger = mLoggerInstanceManager.getPlatformLogger(callingUserId);
impl.removeByQuery(
packageName,
databaseName,
@@ -800,9 +975,32 @@
new SearchSpec(searchSpecBundle));
// Now that the batch has been written. Persist the newly written data.
impl.persistToDisk(PersistType.Code.LITE);
+ ++operationSuccessCount;
invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
} catch (Throwable t) {
+ ++operationFailureCount;
+ statusCode = throwableToFailedResult(t).getResultCode();
invokeCallbackOnError(callback, t);
+ } finally {
+ if (logger != null) {
+ int estimatedBinderLatencyMillis =
+ 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
+ int totalLatencyMillis =
+ (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
+ CallStats.Builder cBuilder = new CallStats.Builder(packageName,
+ databaseName)
+ .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());
+ }
}
});
}
@@ -836,34 +1034,97 @@
}
@Override
- public void persistToDisk(@UserIdInt int userId) {
+ public void persistToDisk(@UserIdInt int userId,
+ @ElapsedRealtimeLong long binderCallStartTimeMillis) {
+ long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
int callingUid = Binder.getCallingUid();
int callingUserId = handleIncomingUser(userId, callingUid);
EXECUTOR.execute(() -> {
+ @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
+ PlatformLogger logger = null;
+ int operationSuccessCount = 0;
+ int operationFailureCount = 0;
try {
verifyUserUnlocked(callingUserId);
AppSearchImpl impl =
mImplInstanceManager.getAppSearchImpl(callingUserId);
+ logger = mLoggerInstanceManager.getPlatformLogger(callingUserId);
impl.persistToDisk(PersistType.Code.FULL);
+ ++operationSuccessCount;
} catch (Throwable t) {
+ ++operationFailureCount;
+ statusCode = throwableToFailedResult(t).getResultCode();
Log.e(TAG, "Unable to persist the data to disk", t);
+ } finally {
+ if (logger != null) {
+ int estimatedBinderLatencyMillis =
+ 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
+ int totalLatencyMillis =
+ (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
+ CallStats.Builder cBuilder = new CallStats.Builder(/*packageName=*/ "",
+ /*databaseName=*/ "")
+ .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());
+ }
}
});
}
@Override
- public void initialize(@UserIdInt int userId, @NonNull IAppSearchResultCallback callback) {
+ public void initialize(@UserIdInt int userId,
+ @ElapsedRealtimeLong long binderCallStartTimeMillis,
+ @NonNull IAppSearchResultCallback callback) {
Objects.requireNonNull(callback);
+ long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
int callingUid = Binder.getCallingUid();
int callingUserId = handleIncomingUser(userId, callingUid);
EXECUTOR.execute(() -> {
+ @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
+ PlatformLogger logger = null;
+ int operationSuccessCount = 0;
+ int operationFailureCount = 0;
try {
verifyUserUnlocked(callingUserId);
- mImplInstanceManager.getOrCreateAppSearchImpl(mContext, callingUserId);
- mLoggerInstanceManager.getOrCreatePlatformLogger(getContext(), callingUserId);
+ logger = mLoggerInstanceManager.getOrCreatePlatformLogger(mContext,
+ callingUserId);
+ mImplInstanceManager.getOrCreateAppSearchImpl(mContext, callingUserId, logger);
+ ++operationSuccessCount;
invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
} catch (Throwable t) {
+ ++operationFailureCount;
+ statusCode = throwableToFailedResult(t).getResultCode();
invokeCallbackOnError(callback, t);
+ } finally {
+ if (logger != null) {
+ int estimatedBinderLatencyMillis =
+ 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=*/ "")
+ .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());
+ }
}
});
}
@@ -960,8 +1221,10 @@
int userId = userHandle.getIdentifier();
try {
verifyUserUnlocked(userId);
- AppSearchImpl impl = mImplInstanceManager.getOrCreateAppSearchImpl(mContext,
+ PlatformLogger logger = mLoggerInstanceManager.getOrCreatePlatformLogger(mContext,
userId);
+ AppSearchImpl impl = mImplInstanceManager.getOrCreateAppSearchImpl(mContext,
+ userId, logger);
stats.dataSize += impl.getStorageInfoForPackage(packageName).getSizeBytes();
} catch (Throwable t) {
Log.e(
@@ -985,8 +1248,10 @@
if (packagesForUid == null) {
return;
}
- AppSearchImpl impl = mImplInstanceManager.getOrCreateAppSearchImpl(mContext,
+ PlatformLogger logger = mLoggerInstanceManager.getOrCreatePlatformLogger(mContext,
userId);
+ AppSearchImpl impl = mImplInstanceManager.getOrCreateAppSearchImpl(mContext,
+ userId, logger);
for (int i = 0; i < packagesForUid.length; i++) {
stats.dataSize +=
impl.getStorageInfoForPackage(packagesForUid[i]).getSizeBytes();
@@ -1012,8 +1277,10 @@
if (packagesForUser == null) {
return;
}
+ PlatformLogger logger = mLoggerInstanceManager.getOrCreatePlatformLogger(mContext,
+ userId);
AppSearchImpl impl =
- mImplInstanceManager.getOrCreateAppSearchImpl(mContext, userId);
+ mImplInstanceManager.getOrCreateAppSearchImpl(mContext, userId, logger);
for (int i = 0; i < packagesForUser.size(); i++) {
String packageName = packagesForUser.get(i).packageName;
stats.dataSize += impl.getStorageInfoForPackage(packageName).getSizeBytes();
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 b815de4..f8bc473 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/ImplInstanceManager.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/ImplInstanceManager.java
@@ -19,6 +19,7 @@
import static android.content.pm.PackageManager.MATCH_FACTORY_ONLY;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.appsearch.exceptions.AppSearchException;
import android.content.Context;
@@ -30,6 +31,7 @@
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.server.appsearch.external.localstorage.AppSearchImpl;
+import com.android.server.appsearch.external.localstorage.AppSearchLogger;
import java.io.File;
@@ -88,16 +90,17 @@
* one will be created.
*
* @param context The context
- * @param userId The multi-user userId of the device user calling AppSearch
+ * @param userId The multi-user userId of the device user calling AppSearch
* @return An initialized {@link AppSearchImpl} for this user
*/
@NonNull
public AppSearchImpl getOrCreateAppSearchImpl(
- @NonNull Context context, @UserIdInt int userId) throws AppSearchException {
+ @NonNull Context context, @UserIdInt int userId, @Nullable AppSearchLogger logger)
+ throws AppSearchException {
synchronized (mInstancesLocked) {
AppSearchImpl instance = mInstancesLocked.get(userId);
if (instance == null) {
- instance = createImpl(context, userId);
+ instance = createImpl(context, userId, logger);
mInstancesLocked.put(userId, instance);
}
return instance;
@@ -164,11 +167,12 @@
}
}
- private AppSearchImpl createImpl(@NonNull Context context, @UserIdInt int userId)
+ private AppSearchImpl createImpl(@NonNull Context context, @UserIdInt int userId,
+ @Nullable AppSearchLogger logger)
throws AppSearchException {
File appSearchDir = getAppSearchDir(userId);
return AppSearchImpl.create(
- appSearchDir, context, userId, mGlobalQuerierPackage, /*logger=*/ null);
+ appSearchDir, context, userId, mGlobalQuerierPackage, logger);
}
/**
@@ -182,10 +186,10 @@
context.getString(R.string.config_globalAppSearchDataQuerierPackage);
try {
if (context.getPackageManager()
- .getPackageInfoAsUser(
- globalAppSearchDataQuerierPackage,
- MATCH_FACTORY_ONLY,
- UserHandle.USER_SYSTEM)
+ .getPackageInfoAsUser(
+ globalAppSearchDataQuerierPackage,
+ MATCH_FACTORY_ONLY,
+ UserHandle.USER_SYSTEM)
== null) {
return "";
}
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 e5e20e7..1cb0cc5 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
@@ -28,6 +28,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.WorkerThread;
+import android.app.appsearch.AppSearchResult;
import android.app.appsearch.AppSearchSchema;
import android.app.appsearch.GenericDocument;
import android.app.appsearch.GetByDocumentIdRequest;
@@ -38,6 +39,7 @@
import android.app.appsearch.SetSchemaResponse;
import android.app.appsearch.StorageInfo;
import android.app.appsearch.exceptions.AppSearchException;
+import android.app.appsearch.util.LogUtil;
import android.content.Context;
import android.os.Bundle;
import android.os.SystemClock;
@@ -147,8 +149,11 @@
private final ReadWriteLock mReadWriteLock = new ReentrantReadWriteLock();
+ private final LogUtil mLogUtil = new LogUtil(TAG);
+
@GuardedBy("mReadWriteLock")
- private final IcingSearchEngine mIcingSearchEngineLocked;
+ @VisibleForTesting
+ final IcingSearchEngine mIcingSearchEngineLocked;
@GuardedBy("mReadWriteLock")
private final VisibilityStore mVisibilityStoreLocked;
@@ -216,7 +221,7 @@
appSearchImpl.initializeVisibilityStore();
long prepareVisibilityStoreLatencyEndMillis = SystemClock.elapsedRealtime();
- if (logger != null && initStatsBuilder != null) {
+ if (logger != null) {
initStatsBuilder
.setTotalLatencyMillis(
(int) (SystemClock.elapsedRealtime() - totalLatencyStartMillis))
@@ -247,66 +252,91 @@
IcingSearchEngineOptions.newBuilder()
.setBaseDir(icingDir.getAbsolutePath())
.build();
+ mLogUtil.piiTrace("Constructing IcingSearchEngine, request", options);
mIcingSearchEngineLocked = new IcingSearchEngine(options);
+ mLogUtil.piiTrace(
+ "Constructing IcingSearchEngine, response",
+ Objects.hashCode(mIcingSearchEngineLocked));
+
mVisibilityStoreLocked =
new VisibilityStore(this, context, userId, globalQuerierPackage);
- InitializeResultProto initializeResultProto = mIcingSearchEngineLocked.initialize();
- if (initStatsBuilder != null) {
- initStatsBuilder
- .setStatusCode(
- statusProtoToAppSearchException(initializeResultProto.getStatus())
- .getResultCode())
- // TODO(b/173532925) how to get DeSyncs value
- .setHasDeSync(false);
- AppSearchLoggerHelper.copyNativeStats(
- initializeResultProto.getInitializeStats(), initStatsBuilder);
- }
-
- long prepareSchemaAndNamespacesLatencyStartMillis = SystemClock.elapsedRealtime();
- SchemaProto schemaProto;
- GetAllNamespacesResultProto getAllNamespacesResultProto = null;
+ // The core initialization procedure. If any part of this fails, we bail into
+ // resetLocked(), deleting all data (but hopefully allowing AppSearchImpl to come up).
try {
- checkSuccess(initializeResultProto.getStatus());
- schemaProto = getSchemaProtoLocked();
- getAllNamespacesResultProto = mIcingSearchEngineLocked.getAllNamespaces();
- checkSuccess(getAllNamespacesResultProto.getStatus());
- } catch (AppSearchException e) {
- Log.w(TAG, "Error initializing, resetting IcingSearchEngine.", e);
- if (initStatsBuilder != null && getAllNamespacesResultProto != null) {
+ mLogUtil.piiTrace("icingSearchEngine.initialize, request");
+ InitializeResultProto initializeResultProto = mIcingSearchEngineLocked.initialize();
+ mLogUtil.piiTrace(
+ "icingSearchEngine.initialize, response",
+ initializeResultProto.getStatus(),
+ initializeResultProto);
+
+ if (initStatsBuilder != null) {
initStatsBuilder
.setStatusCode(
- statusProtoToAppSearchException(
- getAllNamespacesResultProto.getStatus())
- .getResultCode())
+ statusProtoToResultCode(initializeResultProto.getStatus()))
+ // TODO(b/173532925) how to get DeSyncs value
+ .setHasDeSync(false);
+ AppSearchLoggerHelper.copyNativeStats(
+ initializeResultProto.getInitializeStats(), initStatsBuilder);
+ }
+
+ checkSuccess(initializeResultProto.getStatus());
+
+ long prepareSchemaAndNamespacesLatencyStartMillis = SystemClock.elapsedRealtime();
+ SchemaProto schemaProto = getSchemaProtoLocked();
+
+ mLogUtil.piiTrace("init:getAllNamespaces, request");
+ GetAllNamespacesResultProto getAllNamespacesResultProto =
+ mIcingSearchEngineLocked.getAllNamespaces();
+ mLogUtil.piiTrace(
+ "init:getAllNamespaces, response",
+ getAllNamespacesResultProto.getNamespacesCount(),
+ getAllNamespacesResultProto);
+
+ if (initStatsBuilder != null) {
+ initStatsBuilder
+ .setStatusCode(
+ statusProtoToResultCode(
+ getAllNamespacesResultProto.getStatus()))
.setPrepareSchemaAndNamespacesLatencyMillis(
(int)
(SystemClock.elapsedRealtime()
- prepareSchemaAndNamespacesLatencyStartMillis));
}
+
+ checkSuccess(getAllNamespacesResultProto.getStatus());
+
+ // Populate schema map
+ for (SchemaTypeConfigProto schema : schemaProto.getTypesList()) {
+ String prefixedSchemaType = schema.getSchemaType();
+ addToMap(mSchemaMapLocked, getPrefix(prefixedSchemaType), schema);
+ }
+
+ // Populate namespace map
+ for (String prefixedNamespace : getAllNamespacesResultProto.getNamespacesList()) {
+ addToMap(mNamespaceMapLocked, getPrefix(prefixedNamespace), prefixedNamespace);
+ }
+
+ // logging prepare_schema_and_namespaces latency
+ if (initStatsBuilder != null) {
+ initStatsBuilder.setPrepareSchemaAndNamespacesLatencyMillis(
+ (int)
+ (SystemClock.elapsedRealtime()
+ - prepareSchemaAndNamespacesLatencyStartMillis));
+ }
+
+ mLogUtil.piiTrace("Init completed successfully");
+
+ } catch (AppSearchException e) {
// Some error. Reset and see if it fixes it.
- resetLocked();
- return;
+ Log.e(TAG, "Error initializing, resetting IcingSearchEngine.", e);
+ if (initStatsBuilder != null) {
+ initStatsBuilder.setStatusCode(e.getResultCode());
+ }
+ resetLocked(initStatsBuilder);
}
- // Populate schema map
- for (SchemaTypeConfigProto schema : schemaProto.getTypesList()) {
- String prefixedSchemaType = schema.getSchemaType();
- addToMap(mSchemaMapLocked, getPrefix(prefixedSchemaType), schema);
- }
-
- // Populate namespace map
- for (String prefixedNamespace : getAllNamespacesResultProto.getNamespacesList()) {
- addToMap(mNamespaceMapLocked, getPrefix(prefixedNamespace), prefixedNamespace);
- }
-
- // logging prepare_schema_and_namespaces latency
- if (initStatsBuilder != null) {
- initStatsBuilder.setPrepareSchemaAndNamespacesLatencyMillis(
- (int)
- (SystemClock.elapsedRealtime()
- - prepareSchemaAndNamespacesLatencyStartMillis));
- }
} finally {
mReadWriteLock.writeLock().unlock();
}
@@ -321,8 +351,9 @@
mReadWriteLock.writeLock().lock();
try {
throwIfClosedLocked();
-
+ mLogUtil.piiTrace("Initializing VisibilityStore, request");
mVisibilityStoreLocked.initialize();
+ mLogUtil.piiTrace("Initializing VisibilityStore, response");
} finally {
mReadWriteLock.writeLock().unlock();
}
@@ -348,9 +379,10 @@
if (mClosedLocked) {
return;
}
-
persistToDisk(PersistType.Code.FULL);
+ mLogUtil.piiTrace("icingSearchEngine.close, request");
mIcingSearchEngineLocked.close();
+ mLogUtil.piiTrace("icingSearchEngine.close, response");
mClosedLocked = true;
} catch (AppSearchException e) {
Log.w(TAG, "Error when closing AppSearchImpl.", e);
@@ -410,9 +442,12 @@
rewriteSchema(prefix, existingSchemaBuilder, newSchemaBuilder.build());
// Apply schema
+ SchemaProto finalSchema = existingSchemaBuilder.build();
+ mLogUtil.piiTrace("setSchema, request", finalSchema.getTypesCount(), finalSchema);
SetSchemaResultProto setSchemaResultProto =
- mIcingSearchEngineLocked.setSchema(
- existingSchemaBuilder.build(), forceOverride);
+ mIcingSearchEngineLocked.setSchema(finalSchema, forceOverride);
+ mLogUtil.piiTrace(
+ "setSchema, response", setSchemaResultProto.getStatus(), setSchemaResultProto);
// Determine whether it succeeded.
try {
@@ -544,11 +579,16 @@
mReadWriteLock.readLock().lock();
try {
throwIfClosedLocked();
+ mLogUtil.piiTrace("getAllNamespaces, request");
// We can't just use mNamespaceMap here because we have no way to prune namespaces from
// mNamespaceMap when they have no more documents (e.g. after setting schema to empty or
// using deleteByQuery).
GetAllNamespacesResultProto getAllNamespacesResultProto =
mIcingSearchEngineLocked.getAllNamespaces();
+ mLogUtil.piiTrace(
+ "getAllNamespaces, response",
+ getAllNamespacesResultProto.getNamespacesCount(),
+ getAllNamespacesResultProto);
checkSuccess(getAllNamespacesResultProto.getStatus());
String prefix = createPrefix(packageName, databaseName);
List<String> results = new ArrayList<>();
@@ -601,17 +641,18 @@
String prefix = createPrefix(packageName, databaseName);
addPrefixToDocument(documentBuilder, prefix);
long rewriteDocumentTypeEndTimeMillis = SystemClock.elapsedRealtime();
+ DocumentProto finalDocument = documentBuilder.build();
+ mLogUtil.piiTrace("putDocument, request", finalDocument.getUri(), finalDocument);
PutResultProto putResultProto = mIcingSearchEngineLocked.put(documentBuilder.build());
+ mLogUtil.piiTrace("putDocument, response", putResultProto.getStatus(), putResultProto);
addToMap(mNamespaceMapLocked, prefix, documentBuilder.getNamespace());
// Logging stats
- if (logger != null && pStatsBuilder != null) {
+ if (pStatsBuilder != null) {
pStatsBuilder
.getGeneralStatsBuilder()
- .setStatusCode(
- statusProtoToAppSearchException(putResultProto.getStatus())
- .getResultCode());
+ .setStatusCode(statusProtoToResultCode(putResultProto.getStatus()));
pStatsBuilder
.setGenerateDocumentProtoLatencyMillis(
(int)
@@ -629,7 +670,7 @@
} finally {
mReadWriteLock.writeLock().unlock();
- if (logger != null && pStatsBuilder != null) {
+ if (logger != null) {
long totalEndTimeMillis = SystemClock.elapsedRealtime();
pStatsBuilder
.getGeneralStatsBuilder()
@@ -685,8 +726,14 @@
.addAllTypePropertyMasks(prefixedPropertyMasks)
.build();
+ String finalNamespace = createPrefix(packageName, databaseName) + namespace;
+ if (mLogUtil.isPiiTraceEnabled()) {
+ mLogUtil.piiTrace(
+ "getDocument, request", finalNamespace + ", " + id + "," + getResultSpec);
+ }
GetResultProto getResultProto =
- mIcingSearchEngineLocked.get(prefix + namespace, id, getResultSpec);
+ mIcingSearchEngineLocked.get(finalNamespace, id, getResultSpec);
+ mLogUtil.piiTrace("getDocument, response", getResultProto.getStatus(), getResultProto);
checkSuccess(getResultProto.getStatus());
// The schema type map cannot be null at this point. It could only be null if no
@@ -754,7 +801,7 @@
sStatsBuilder);
} finally {
mReadWriteLock.readLock().unlock();
- if (logger != null && sStatsBuilder != null) {
+ if (logger != null) {
sStatsBuilder.setTotalLatencyMillis(
(int) (SystemClock.elapsedRealtime() - totalLatencyStartMillis));
logger.logStats(sStatsBuilder.build());
@@ -832,9 +879,10 @@
}
} else {
// Client didn't specify certain schemas to search over, check all schemas
- Set<String> prefixedSchemas = mSchemaMapLocked.get(prefix).keySet();
+ Map<String, SchemaTypeConfigProto> prefixedSchemas =
+ mSchemaMapLocked.get(prefix);
if (prefixedSchemas != null) {
- for (String prefixedSchema : prefixedSchemas) {
+ for (String prefixedSchema : prefixedSchemas.keySet()) {
if (packageName.equals(callerPackageName)
|| mVisibilityStoreLocked.isSchemaSearchableByCaller(
prefix, prefixedSchema, callerUid)) {
@@ -854,7 +902,7 @@
} finally {
mReadWriteLock.readLock().unlock();
- if (logger != null && sStatsBuilder != null) {
+ if (logger != null) {
sStatsBuilder.setTotalLatencyMillis(
(int) (SystemClock.elapsedRealtime() - totalLatencyStartMillis));
logger.logStats(sStatsBuilder.build());
@@ -938,18 +986,25 @@
rewriteResultSpecForPrefixesLocked(resultSpecBuilder, prefixes, allowedPrefixedSchemas);
ScoringSpecProto scoringSpec = SearchSpecToProtoConverter.toScoringSpecProto(searchSpec);
+ SearchSpecProto finalSearchSpec = searchSpecBuilder.build();
+ ResultSpecProto finalResultSpec = resultSpecBuilder.build();
long rewriteSearchSpecLatencyEndMillis = SystemClock.elapsedRealtime();
+ if (mLogUtil.isPiiTraceEnabled()) {
+ mLogUtil.piiTrace(
+ "search, request",
+ finalSearchSpec.getQuery(),
+ finalSearchSpec + ", " + scoringSpec + ", " + finalResultSpec);
+ }
SearchResultProto searchResultProto =
- mIcingSearchEngineLocked.search(
- searchSpecBuilder.build(), scoringSpec, resultSpecBuilder.build());
+ mIcingSearchEngineLocked.search(finalSearchSpec, scoringSpec, finalResultSpec);
+ mLogUtil.piiTrace(
+ "search, response", searchResultProto.getResultsCount(), searchResultProto);
if (sStatsBuilder != null) {
sStatsBuilder
- .setStatusCode(
- statusProtoToAppSearchException(searchResultProto.getStatus())
- .getResultCode())
+ .setStatusCode(statusProtoToResultCode(searchResultProto.getStatus()))
.setRewriteSearchSpecLatencyMillis(
(int)
(rewriteSearchSpecLatencyEndMillis
@@ -985,8 +1040,13 @@
try {
throwIfClosedLocked();
+ mLogUtil.piiTrace("getNextPage, request", nextPageToken);
SearchResultProto searchResultProto =
mIcingSearchEngineLocked.getNextPage(nextPageToken);
+ mLogUtil.piiTrace(
+ "getNextPage, response",
+ searchResultProto.getResultsCount(),
+ searchResultProto);
checkSuccess(searchResultProto.getStatus());
return rewriteSearchResultProto(searchResultProto, mSchemaMapLocked);
} finally {
@@ -1007,6 +1067,7 @@
try {
throwIfClosedLocked();
+ mLogUtil.piiTrace("invalidateNextPageToken, request", nextPageToken);
mIcingSearchEngineLocked.invalidateNextPageToken(nextPageToken);
} finally {
mReadWriteLock.readLock().unlock();
@@ -1039,7 +1100,9 @@
.setUsageType(usageType)
.build();
+ mLogUtil.piiTrace("reportUsage, request", report.getDocumentUri(), report);
ReportUsageResultProto result = mIcingSearchEngineLocked.reportUsage(report);
+ mLogUtil.piiTrace("reportUsage, response", result.getStatus(), result);
checkSuccess(result.getStatus());
} finally {
mReadWriteLock.writeLock().unlock();
@@ -1068,9 +1131,13 @@
throwIfClosedLocked();
String prefixedNamespace = createPrefix(packageName, databaseName) + namespace;
+ if (mLogUtil.isPiiTraceEnabled()) {
+ mLogUtil.piiTrace("removeById, request", prefixedNamespace + ", " + id);
+ }
DeleteResultProto deleteResultProto =
mIcingSearchEngineLocked.delete(prefixedNamespace, id);
-
+ mLogUtil.piiTrace(
+ "removeById, response", deleteResultProto.getStatus(), deleteResultProto);
checkSuccess(deleteResultProto.getStatus());
} finally {
mReadWriteLock.writeLock().unlock();
@@ -1121,8 +1188,12 @@
searchSpecBuilder, Collections.singleton(prefix), allowedPrefixedSchemas)) {
return;
}
+ SearchSpecProto finalSearchSpec = searchSpecBuilder.build();
+ mLogUtil.piiTrace("removeByQuery, request", finalSearchSpec);
DeleteByQueryResultProto deleteResultProto =
- mIcingSearchEngineLocked.deleteByQuery(searchSpecBuilder.build());
+ mIcingSearchEngineLocked.deleteByQuery(finalSearchSpec);
+ mLogUtil.piiTrace(
+ "removeByQuery, response", deleteResultProto.getStatus(), deleteResultProto);
// It seems that the caller wants to get success if the data matching the query is
// not in the DB because it was not there or was successfully deleted.
@@ -1202,7 +1273,10 @@
@NonNull
private StorageInfo getStorageInfoForNamespacesLocked(@NonNull Set<String> prefixedNamespaces)
throws AppSearchException {
+ mLogUtil.piiTrace("getStorageInfo, request");
StorageInfoResultProto storageInfoResult = mIcingSearchEngineLocked.getStorageInfo();
+ mLogUtil.piiTrace(
+ "getStorageInfo, response", storageInfoResult.getStatus(), storageInfoResult);
checkSuccess(storageInfoResult.getStatus());
if (!storageInfoResult.hasStorageInfo()
|| !storageInfoResult.getStorageInfo().hasDocumentStorageInfo()) {
@@ -1277,8 +1351,13 @@
try {
throwIfClosedLocked();
+ mLogUtil.piiTrace("persistToDisk, request", persistType);
PersistToDiskResultProto persistToDiskResultProto =
mIcingSearchEngineLocked.persistToDisk(persistType);
+ mLogUtil.piiTrace(
+ "persistToDisk, response",
+ persistToDiskResultProto.getStatus(),
+ persistToDiskResultProto);
checkSuccess(persistToDiskResultProto.getStatus());
} finally {
mReadWriteLock.writeLock().unlock();
@@ -1305,12 +1384,21 @@
newSchemaBuilder.addTypes(existingSchema.getTypes(i));
}
}
+ SchemaProto finalSchema = newSchemaBuilder.build();
// Apply schema, set force override to true to remove all schemas and documents under
// that package.
+ mLogUtil.piiTrace(
+ "clearPackageData.setSchema, request",
+ finalSchema.getTypesCount(),
+ finalSchema);
SetSchemaResultProto setSchemaResultProto =
mIcingSearchEngineLocked.setSchema(
- newSchemaBuilder.build(), /*ignoreErrorsAndDeleteDocuments=*/ true);
+ finalSchema, /*ignoreErrorsAndDeleteDocuments=*/ true);
+ mLogUtil.piiTrace(
+ "clearPackageData.setSchema, response",
+ setSchemaResultProto.getStatus(),
+ setSchemaResultProto);
// Determine whether it succeeded.
checkSuccess(setSchemaResultProto.getStatus());
@@ -1330,12 +1418,24 @@
* @throws AppSearchException on IcingSearchEngine error.
*/
@GuardedBy("mReadWriteLock")
- private void resetLocked() throws AppSearchException {
+ private void resetLocked(@Nullable InitializeStats.Builder initStatsBuilder)
+ throws AppSearchException {
+ mLogUtil.piiTrace("icingSearchEngine.reset, request");
ResetResultProto resetResultProto = mIcingSearchEngineLocked.reset();
+ mLogUtil.piiTrace(
+ "icingSearchEngine.reset, response",
+ resetResultProto.getStatus(),
+ resetResultProto);
mOptimizeIntervalCountLocked = 0;
mSchemaMapLocked.clear();
mNamespaceMapLocked.clear();
+ if (initStatsBuilder != null) {
+ initStatsBuilder
+ .setHasReset(true)
+ .setResetStatusCode(statusProtoToResultCode(resetResultProto.getStatus()));
+ }
+
// Must be called after everything else since VisibilityStore may repopulate
// IcingSearchEngine with an initial schema.
mVisibilityStoreLocked.handleReset();
@@ -1472,15 +1572,17 @@
// Empty namespaces on the search spec means to query over all namespaces.
Set<String> existingNamespaces = mNamespaceMapLocked.get(prefix);
- if (namespaceFilters.isEmpty()) {
- // Include all namespaces
- searchSpecBuilder.addAllNamespaceFilters(existingNamespaces);
- } else {
- // Prefix the given namespaces.
- for (int i = 0; i < namespaceFilters.size(); i++) {
- String prefixedNamespace = prefix + namespaceFilters.get(i);
- if (existingNamespaces.contains(prefixedNamespace)) {
- searchSpecBuilder.addNamespaceFilters(prefixedNamespace);
+ if (existingNamespaces != null) {
+ if (namespaceFilters.isEmpty()) {
+ // Include all namespaces
+ searchSpecBuilder.addAllNamespaceFilters(existingNamespaces);
+ } else {
+ // Prefix the given namespaces.
+ for (int i = 0; i < namespaceFilters.size(); i++) {
+ String prefixedNamespace = prefix + namespaceFilters.get(i);
+ if (existingNamespaces.contains(prefixedNamespace)) {
+ searchSpecBuilder.addNamespaceFilters(prefixedNamespace);
+ }
}
}
}
@@ -1581,6 +1683,9 @@
Map<String, List<String>> packageAndNamespaceToNamespaces = new ArrayMap<>();
for (String prefix : existingPrefixes) {
Set<String> prefixedNamespaces = mNamespaceMapLocked.get(prefix);
+ if (prefixedNamespaces == null) {
+ continue;
+ }
String packageName = getPackageName(prefix);
// Create a new prefix without the database name. This will allow us to group namespaces
// that have the same name and package but a different database name together.
@@ -1636,6 +1741,9 @@
Map<String, List<String>> packageToNamespacesMap = new ArrayMap<>();
for (String prefix : existingPrefixes) {
Set<String> prefixedNamespaces = mNamespaceMapLocked.get(prefix);
+ if (prefixedNamespaces == null) {
+ continue;
+ }
String packageName = getPackageName(prefix);
List<String> packageNamespaceList = packageToNamespacesMap.get(packageName);
if (packageNamespaceList == null) {
@@ -1677,6 +1785,9 @@
Map<String, List<String>> namespaceToPrefixedNamespaces = new ArrayMap<>();
for (String prefix : existingPrefixes) {
Set<String> prefixedNamespaces = mNamespaceMapLocked.get(prefix);
+ if (prefixedNamespaces == null) {
+ continue;
+ }
for (String prefixedNamespace : prefixedNamespaces) {
String namespace;
try {
@@ -1707,7 +1818,9 @@
@VisibleForTesting
@GuardedBy("mReadWriteLock")
SchemaProto getSchemaProtoLocked() throws AppSearchException {
+ mLogUtil.piiTrace("getSchema, request");
GetSchemaResultProto schemaProto = mIcingSearchEngineLocked.getSchema();
+ mLogUtil.piiTrace("getSchema, response", schemaProto.getStatus(), schemaProto);
// TODO(b/161935693) check GetSchemaResultProto is success or not. Call reset() if it's not.
// TODO(b/161935693) only allow GetSchemaResultProto NOT_FOUND on first run
checkCodeOneOf(schemaProto.getStatus(), StatusProto.Code.OK, StatusProto.Code.NOT_FOUND);
@@ -1781,7 +1894,9 @@
return;
}
- throw statusProtoToAppSearchException(statusProto);
+ throw new AppSearchException(
+ ResultCodeToProtoConverter.toResultCode(statusProto.getCode()),
+ statusProto.getMessage());
}
/**
@@ -1849,7 +1964,10 @@
public void optimize() throws AppSearchException {
mReadWriteLock.writeLock().lock();
try {
+ mLogUtil.piiTrace("optimize, request");
OptimizeResultProto optimizeResultProto = mIcingSearchEngineLocked.optimize();
+ mLogUtil.piiTrace(
+ "optimize, response", optimizeResultProto.getStatus(), optimizeResultProto);
checkSuccess(optimizeResultProto.getStatus());
} finally {
mReadWriteLock.writeLock().unlock();
@@ -1887,7 +2005,10 @@
@GuardedBy("mReadWriteLock")
@VisibleForTesting
GetOptimizeInfoResultProto getOptimizeInfoResultLocked() {
- return mIcingSearchEngineLocked.getOptimizeInfo();
+ mLogUtil.piiTrace("getOptimizeInfo, request");
+ GetOptimizeInfoResultProto result = mIcingSearchEngineLocked.getOptimizeInfo();
+ mLogUtil.piiTrace("getOptimizeInfo, response", result.getStatus(), result);
+ return result;
}
@GuardedBy("mReadWriteLock")
@@ -1898,16 +2019,16 @@
}
/**
- * Converts an erroneous status code to an AppSearchException. Callers should ensure that the
- * status code is not OK or WARNING_DATA_LOSS.
+ * Converts an erroneous status code from the Icing status enums to the AppSearchResult enums.
*
- * @param statusProto StatusProto with error code and message to translate into
- * AppSearchException.
- * @return AppSearchException with the parallel error code.
+ * <p>Callers should ensure that the status code is not OK or WARNING_DATA_LOSS.
+ *
+ * @param statusProto StatusProto with error code to translate into an {@link AppSearchResult}
+ * code.
+ * @return {@link AppSearchResult} error code
*/
- private static AppSearchException statusProtoToAppSearchException(StatusProto statusProto) {
- return new AppSearchException(
- ResultCodeToProtoConverter.toResultCode(statusProto.getCode()),
- statusProto.getMessage());
+ private static @AppSearchResult.ResultCode int statusProtoToResultCode(
+ @NonNull StatusProto statusProto) {
+ return ResultCodeToProtoConverter.toResultCode(statusProto.getCode());
}
}
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchLoggerHelper.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchLoggerHelper.java
index 4a5ecf1..4b92ce6 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchLoggerHelper.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchLoggerHelper.java
@@ -103,8 +103,7 @@
toStatsBuilder
.setNativeLatencyMillis(fromNativeStats.getLatencyMs())
.setTermCount(fromNativeStats.getNumTerms())
- // TODO(b/173532925) query length missing in native
- // .setNativeQueryLength(0)
+ .setQueryLength(fromNativeStats.getQueryLength())
.setFilteredNamespaceCount(fromNativeStats.getNumNamespacesFiltered())
.setFilteredSchemaTypeCount(fromNativeStats.getNumSchemaTypesFiltered())
.setRequestedPageSize(fromNativeStats.getRequestedPageSize())
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/GenericDocumentToProtoConverter.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/GenericDocumentToProtoConverter.java
index 0cdad37..9ce916f 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/GenericDocumentToProtoConverter.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/GenericDocumentToProtoConverter.java
@@ -199,7 +199,7 @@
case AppSearchSchema.PropertyConfig.DATA_TYPE_STRING:
documentBuilder.setPropertyString(propertyName, EMPTY_STRING_ARRAY);
break;
- case AppSearchSchema.PropertyConfig.DATA_TYPE_INT64:
+ case AppSearchSchema.PropertyConfig.DATA_TYPE_LONG:
documentBuilder.setPropertyLong(propertyName, EMPTY_LONG_ARRAY);
break;
case AppSearchSchema.PropertyConfig.DATA_TYPE_DOUBLE:
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverter.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverter.java
index 80f7007..3e4e7d2 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverter.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverter.java
@@ -133,7 +133,7 @@
case STRING:
return toStringPropertyConfig(proto);
case INT64:
- return new AppSearchSchema.Int64PropertyConfig.Builder(proto.getPropertyName())
+ return new AppSearchSchema.LongPropertyConfig.Builder(proto.getPropertyName())
.setCardinality(proto.getCardinality().getNumber())
.build();
case DOUBLE:
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/InitializeStats.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/InitializeStats.java
index 5364a0c..72befa7 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/InitializeStats.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/InitializeStats.java
@@ -106,6 +106,10 @@
private final int mNativeNumDocuments;
/** Returns number of schema types currently in the schema store. */
private final int mNativeNumSchemaTypes;
+ /** Whether we had to reset the index, losing all data, during initialization. */
+ private final boolean mHasReset;
+ /** If we had to reset, contains the status code of the reset operation. */
+ @AppSearchResult.ResultCode private final int mResetStatusCode;
/** Returns the status of the initialization. */
@AppSearchResult.ResultCode
@@ -214,6 +218,21 @@
return mNativeNumSchemaTypes;
}
+ /** Returns whether we had to reset the index, losing all data, as part of initialization. */
+ public boolean hasReset() {
+ return mHasReset;
+ }
+
+ /**
+ * Returns the status of the reset, if one was performed according to {@link #hasReset}.
+ *
+ * <p>If no value has been set, the default value is {@link AppSearchResult#RESULT_OK}.
+ */
+ @AppSearchResult.ResultCode
+ public int getResetStatusCode() {
+ return mResetStatusCode;
+ }
+
InitializeStats(@NonNull Builder builder) {
Objects.requireNonNull(builder);
mStatusCode = builder.mStatusCode;
@@ -232,11 +251,14 @@
mNativeDocumentStoreDataStatus = builder.mNativeDocumentStoreDataStatus;
mNativeNumDocuments = builder.mNativeNumDocuments;
mNativeNumSchemaTypes = builder.mNativeNumSchemaTypes;
+ mHasReset = builder.mHasReset;
+ mResetStatusCode = builder.mResetStatusCode;
}
/** Builder for {@link InitializeStats}. */
public static class Builder {
@AppSearchResult.ResultCode int mStatusCode;
+
int mTotalLatencyMillis;
boolean mHasDeSync;
int mPrepareSchemaAndNamespacesLatencyMillis;
@@ -251,6 +273,8 @@
@DocumentStoreDataStatus int mNativeDocumentStoreDataStatus;
int mNativeNumDocuments;
int mNativeNumSchemaTypes;
+ boolean mHasReset;
+ @AppSearchResult.ResultCode int mResetStatusCode;
/** Sets the status of the initialization. */
@NonNull
@@ -392,6 +416,20 @@
return this;
}
+ /** Sets whether we had to reset the index, losing all data, as part of initialization. */
+ @NonNull
+ public Builder setHasReset(boolean hasReset) {
+ mHasReset = hasReset;
+ return this;
+ }
+
+ /** Sets the status of the reset, if one was performed according to {@link #setHasReset}. */
+ @NonNull
+ public Builder setResetStatusCode(@AppSearchResult.ResultCode int resetStatusCode) {
+ mResetStatusCode = resetStatusCode;
+ return this;
+ }
+
/**
* Constructs a new {@link InitializeStats} from the contents of this {@link
* InitializeStats.Builder}
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/RemoveStats.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/RemoveStats.java
new file mode 100644
index 0000000..b900c49
--- /dev/null
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/RemoveStats.java
@@ -0,0 +1,181 @@
+/*
+ * 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.IntDef;
+import android.annotation.NonNull;
+import android.app.appsearch.AppSearchResult;
+import android.app.appsearch.RemoveByDocumentIdRequest;
+import android.app.appsearch.SearchSpec;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
+
+/**
+ * Class holds detailed stats for {@link
+ * android.app.appsearch.AppSearchSession#remove(RemoveByDocumentIdRequest)} and {@link
+ * android.app.appsearch.AppSearchSession#remove(String, SearchSpec)}
+ *
+ * @hide
+ */
+public final class RemoveStats {
+ @IntDef(
+ value = {
+ // It needs to be sync with DeleteType.Code in
+ // external/icing/proto/icing/proto/logging.proto#DeleteStatsProto
+ UNKNOWN,
+ SINGLE,
+ QUERY,
+ NAMESPACE,
+ SCHEMA_TYPE,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface DeleteType {}
+
+ /** Default. Should never be used. */
+ public static final int UNKNOWN = 0;
+ /** Delete by namespace + id. */
+ public static final int SINGLE = 1;
+ /** Delete by query. */
+ public static final int QUERY = 2;
+ /** Delete by namespace. */
+ public static final int NAMESPACE = 3;
+ /** Delete by schema type. */
+ public static final int SCHEMA_TYPE = 4;
+
+ @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;
+ private final int mNativeLatencyMillis;
+ @DeleteType private final int mNativeDeleteType;
+ private final int mNativeNumDocumentsDeleted;
+
+ RemoveStats(@NonNull Builder builder) {
+ Objects.requireNonNull(builder);
+ mPackageName = builder.mPackageName;
+ mDatabase = builder.mDatabase;
+ mStatusCode = builder.mStatusCode;
+ mTotalLatencyMillis = builder.mTotalLatencyMillis;
+ mNativeLatencyMillis = builder.mNativeLatencyMillis;
+ mNativeDeleteType = builder.mNativeDeleteType;
+ mNativeNumDocumentsDeleted = builder.mNativeNumDocumentsDeleted;
+ }
+
+ /** Returns calling package name. */
+ @NonNull
+ public String getPackageName() {
+ return mPackageName;
+ }
+
+ /** Returns calling database name. */
+ @NonNull
+ public String getDatabase() {
+ return mDatabase;
+ }
+
+ /** Returns status code for this remove. */
+ @AppSearchResult.ResultCode
+ public int getStatusCode() {
+ return mStatusCode;
+ }
+
+ /** Returns total latency of this remove in millis. */
+ public int getTotalLatencyMillis() {
+ return mTotalLatencyMillis;
+ }
+
+ /** Returns how much time in millis spent in the native code. */
+ public int getNativeLatencyMillis() {
+ return mNativeLatencyMillis;
+ }
+
+ /** Returns what type of delete for this remove call. */
+ @DeleteType
+ public int getDeleteType() {
+ return mNativeDeleteType;
+ }
+
+ /** Returns how many documents get deleted in this call. */
+ public int getDeletedDocumentCount() {
+ return mNativeNumDocumentsDeleted;
+ }
+
+ /** Builder for {@link RemoveStats}. */
+ public static class Builder {
+ @NonNull final String mPackageName;
+ @NonNull final String mDatabase;
+ @AppSearchResult.ResultCode int mStatusCode;
+ int mTotalLatencyMillis;
+ int mNativeLatencyMillis;
+ @DeleteType int mNativeDeleteType;
+ int mNativeNumDocumentsDeleted;
+
+ /** Constructor for the {@link Builder}. */
+ public Builder(@NonNull String packageName, @NonNull String database) {
+ mPackageName = Objects.requireNonNull(packageName);
+ mDatabase = Objects.requireNonNull(database);
+ }
+
+ /** Sets the status code. */
+ @NonNull
+ 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 native latency in millis. */
+ @NonNull
+ public Builder setNativeLatencyMillis(int nativeLatencyMillis) {
+ mNativeLatencyMillis = nativeLatencyMillis;
+ return this;
+ }
+
+ /** Sets delete type for this call. */
+ @NonNull
+ public Builder setDeleteType(@DeleteType int nativeDeleteType) {
+ mNativeDeleteType = nativeDeleteType;
+ return this;
+ }
+
+ /** Sets how many documents get deleted for this call. */
+ @NonNull
+ public Builder setDeletedDocumentCount(int nativeNumDocumentsDeleted) {
+ mNativeNumDocumentsDeleted = nativeNumDocumentsDeleted;
+ return this;
+ }
+
+ /** Creates a {@link RemoveStats}. */
+ @NonNull
+ public RemoveStats build() {
+ return new RemoveStats(/* builder= */ this);
+ }
+ }
+}
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/util/PrefixUtil.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/util/PrefixUtil.java
index 9ae9f18..80cfe89 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/util/PrefixUtil.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/util/PrefixUtil.java
@@ -112,8 +112,11 @@
return prefixedString.substring(delimiterIndex + 1);
}
throw new AppSearchException(
- AppSearchResult.RESULT_UNKNOWN_ERROR,
- "The prefixed value doesn't contains a valid database name.");
+ AppSearchResult.RESULT_INTERNAL_ERROR,
+ "The prefixed value \""
+ + prefixedString
+ + "\" doesn't contain a valid "
+ + "database name");
}
/**
@@ -128,8 +131,11 @@
int databaseDelimiterIndex = prefixedString.indexOf(DATABASE_DELIMITER);
if (databaseDelimiterIndex == -1) {
throw new AppSearchException(
- AppSearchResult.RESULT_UNKNOWN_ERROR,
- "The databaseName prefixed value doesn't contain a valid database name.");
+ AppSearchResult.RESULT_INTERNAL_ERROR,
+ "The prefixed value \""
+ + prefixedString
+ + "\" doesn't contain a valid "
+ + "database name");
}
// Add 1 to include the char size of the DATABASE_DELIMITER
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 88f238e..df59306 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
@@ -17,6 +17,7 @@
package com.android.server.appsearch.stats;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.app.appsearch.exceptions.AppSearchException;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -193,12 +194,22 @@
@Override
public void logStats(@NonNull InitializeStats stats) throws AppSearchException {
- // TODO(b/173532925): Implement
+ Objects.requireNonNull(stats);
+ synchronized (mLock) {
+ if (shouldLogForTypeLocked(CallStats.CALL_TYPE_INITIALIZE)) {
+ logStatsImplLocked(stats);
+ }
+ }
}
@Override
public void logStats(@NonNull SearchStats stats) throws AppSearchException {
- // TODO(b/173532925): Implement
+ Objects.requireNonNull(stats);
+ synchronized (mLock) {
+ if (shouldLogForTypeLocked(CallStats.CALL_TYPE_SEARCH)) {
+ logStatsImplLocked(stats);
+ }
+ }
}
/**
@@ -242,7 +253,9 @@
//
// Something is wrong while calculating the hash code for database
// this shouldn't happen since we always use "MD5" and "UTF-8"
- Log.e(TAG, "Error calculating hash code for database " + database, e);
+ if (database != null) {
+ Log.e(TAG, "Error calculating hash code for database " + database, e);
+ }
}
}
@@ -277,21 +290,102 @@
//
// Something is wrong while calculating the hash code for database
// this shouldn't happen since we always use "MD5" and "UTF-8"
- Log.e(TAG, "Error calculating hash code for database " + database, e);
+ if (database != null) {
+ Log.e(TAG, "Error calculating hash code for database " + database, e);
+ }
}
}
+ @GuardedBy("mLock")
+ private void logStatsImplLocked(@NonNull SearchStats stats) {
+ mLastPushTimeMillisLocked = SystemClock.elapsedRealtime();
+ ExtraStats extraStats = createExtraStatsLocked(stats.getPackageName(),
+ CallStats.CALL_TYPE_SEARCH);
+ String database = stats.getDatabase();
+ try {
+ int hashCodeForDatabase = calculateHashCodeMd5(database);
+ FrameworkStatsLog.write(FrameworkStatsLog.APP_SEARCH_QUERY_STATS_REPORTED,
+ extraStats.mSamplingRatio,
+ extraStats.mSkippedSampleCount,
+ extraStats.mPackageUid,
+ hashCodeForDatabase,
+ stats.getStatusCode(),
+ stats.getTotalLatencyMillis(),
+ stats.getRewriteSearchSpecLatencyMillis(),
+ stats.getRewriteSearchResultLatencyMillis(),
+ stats.getVisibilityScope(),
+ stats.getNativeLatencyMillis(),
+ stats.getTermCount(),
+ stats.getQueryLength(),
+ stats.getFilteredNamespaceCount(),
+ stats.getFilteredSchemaTypeCount(),
+ stats.getRequestedPageSize(),
+ stats.getCurrentPageReturnedResultCount(),
+ stats.isFirstPage(),
+ stats.getParseQueryLatencyMillis(),
+ stats.getRankingStrategy(),
+ stats.getScoredDocumentCount(),
+ stats.getScoringLatencyMillis(),
+ stats.getRankingLatencyMillis(),
+ stats.getDocumentRetrievingLatencyMillis(),
+ stats.getResultWithSnippetsCount());
+ } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
+ // TODO(b/184204720) report hashing error to Westworld
+ // We need to set a special value(e.g. 0xFFFFFFFF) for the hashing of the database,
+ // so in the dashboard we know there is some error for hashing.
+ //
+ // Something is wrong while calculating the hash code for database
+ // this shouldn't happen since we always use "MD5" and "UTF-8"
+ if (database != null) {
+ Log.e(TAG, "Error calculating hash code for database " + database, e);
+ }
+ }
+ }
+
+ @GuardedBy("mLock")
+ private void logStatsImplLocked(@NonNull InitializeStats stats) {
+ mLastPushTimeMillisLocked = SystemClock.elapsedRealtime();
+ ExtraStats extraStats = createExtraStatsLocked(/*packageName=*/ null,
+ CallStats.CALL_TYPE_INITIALIZE);
+ FrameworkStatsLog.write(FrameworkStatsLog.APP_SEARCH_INITIALIZE_STATS_REPORTED,
+ extraStats.mSamplingRatio,
+ extraStats.mSkippedSampleCount,
+ extraStats.mPackageUid,
+ stats.getStatusCode(),
+ stats.getTotalLatencyMillis(),
+ stats.hasDeSync(),
+ stats.getPrepareSchemaAndNamespacesLatencyMillis(),
+ stats.getPrepareVisibilityStoreLatencyMillis(),
+ stats.getNativeLatencyMillis(),
+ stats.getDocumentStoreRecoveryCause(),
+ stats.getIndexRestorationCause(),
+ stats.getSchemaStoreRecoveryCause(),
+ stats.getDocumentStoreRecoveryLatencyMillis(),
+ stats.getIndexRestorationLatencyMillis(),
+ stats.getSchemaStoreRecoveryLatencyMillis(),
+ stats.getDocumentStoreDataStatus(),
+ stats.getDocumentCount(),
+ stats.getSchemaTypeCount());
+ }
+
/**
* Calculate the hash code as an integer by returning the last four bytes of its MD5.
*
* @param str a string
- * @return hash code as an integer
+ * @return hash code as an integer. returns -1 if str is null.
* @throws AppSearchException if either algorithm or encoding does not exist.
*/
@VisibleForTesting
@NonNull
- static int calculateHashCodeMd5(@NonNull String str) throws
+ static int calculateHashCodeMd5(@Nullable String str) throws
NoSuchAlgorithmException, UnsupportedEncodingException {
+ if (str == null) {
+ // Just return -1 if caller doesn't have database name
+ // For some stats like globalQuery, databaseName can be null.
+ // Since in atom it is an integer, we have to return something here.
+ return -1;
+ }
+
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(str.getBytes(/*charsetName=*/ "UTF-8"));
byte[] digest = md.digest();
@@ -314,12 +408,19 @@
* <p>This method is called by most of logToWestworldLocked functions to reduce code
* duplication.
*/
+ // TODO(b/173532925) Once we add CTS test for logging atoms and can inspect the result, we can
+ // remove this @VisibleForTesting and directly use PlatformLogger.logStats to test sampling and
+ // rate limiting.
@VisibleForTesting
@GuardedBy("mLock")
@NonNull
- ExtraStats createExtraStatsLocked(@NonNull String packageName,
+ ExtraStats createExtraStatsLocked(@Nullable String packageName,
@CallStats.CallType int callType) {
- int packageUid = getPackageUidAsUserLocked(packageName);
+ int packageUid = Process.INVALID_UID;
+ if (packageName != null) {
+ packageUid = getPackageUidAsUserLocked(packageName);
+ }
+
int samplingRatio = mConfig.mSamplingRatios.get(callType,
mConfig.mDefaultSamplingRatio);
@@ -337,6 +438,9 @@
* stats.
*/
@GuardedBy("mLock")
+ // TODO(b/173532925) Once we add CTS test for logging atoms and can inspect the result, we can
+ // remove this @VisibleForTesting and directly use PlatformLogger.logStats to test sampling and
+ // rate limiting.
@VisibleForTesting
boolean shouldLogForTypeLocked(@CallStats.CallType int callType) {
int samplingRatio = mConfig.mSamplingRatios.get(callType,
diff --git a/apex/appsearch/synced_jetpack_changeid.txt b/apex/appsearch/synced_jetpack_changeid.txt
index 85d85aa..9bfe071 100644
--- a/apex/appsearch/synced_jetpack_changeid.txt
+++ b/apex/appsearch/synced_jetpack_changeid.txt
@@ -1 +1 @@
-I0216abecc41d020f16ed8947a9f37b710afd331e
+c6630eba424d98dd54ece674e769d9b0b883e410
diff --git a/apex/appsearch/testing/java/com/android/server/appsearch/testing/external/AppSearchSessionShim.java b/apex/appsearch/testing/java/com/android/server/appsearch/testing/external/AppSearchSessionShim.java
index a70d9b5..d6ce3eb 100644
--- a/apex/appsearch/testing/java/com/android/server/appsearch/testing/external/AppSearchSessionShim.java
+++ b/apex/appsearch/testing/java/com/android/server/appsearch/testing/external/AppSearchSessionShim.java
@@ -30,6 +30,9 @@
* <p>An {@link AppSearchSessionShim} instance provides access to database operations such as
* setting a schema, adding documents, and searching.
*
+ * <p>Instances of this interface are usually obtained from a storage implementation, e.g. {@code
+ * AppSearchManager.createSearchSession()} or {@code PlatformStorage.createSearchSession()}.
+ *
* <p>All implementations of this interface must be thread safe.
*
* @see GlobalSearchSessionShim
diff --git a/apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java b/apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java
index 22ee501..38500af 100644
--- a/apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java
+++ b/apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java
@@ -258,8 +258,7 @@
public @NonNull ParcelFileDescriptor openBlob(@NonNull BlobHandle blobHandle)
throws IOException {
try {
- return mService.openBlob(blobHandle, mContext.getOpPackageName(),
- mContext.getAttributionTag());
+ return mService.openBlob(blobHandle, mContext.getOpPackageName());
} catch (ParcelableException e) {
e.maybeRethrow(IOException.class);
throw new RuntimeException(e);
@@ -316,7 +315,7 @@
@CurrentTimeMillisLong long leaseExpiryTimeMillis) throws IOException {
try {
mService.acquireLease(blobHandle, descriptionResId, null, leaseExpiryTimeMillis,
- mContext.getOpPackageName(), mContext.getAttributionTag());
+ mContext.getOpPackageName());
} catch (ParcelableException e) {
e.maybeRethrow(IOException.class);
e.maybeRethrow(LimitExceededException.class);
@@ -379,7 +378,7 @@
@CurrentTimeMillisLong long leaseExpiryTimeMillis) throws IOException {
try {
mService.acquireLease(blobHandle, INVALID_RES_ID, description, leaseExpiryTimeMillis,
- mContext.getOpPackageName(), mContext.getAttributionTag());
+ mContext.getOpPackageName());
} catch (ParcelableException e) {
e.maybeRethrow(IOException.class);
e.maybeRethrow(LimitExceededException.class);
@@ -498,8 +497,7 @@
*/
public void releaseLease(@NonNull BlobHandle blobHandle) throws IOException {
try {
- mService.releaseLease(blobHandle, mContext.getOpPackageName(),
- mContext.getAttributionTag());
+ mService.releaseLease(blobHandle, mContext.getOpPackageName());
} catch (ParcelableException e) {
e.maybeRethrow(IOException.class);
throw new RuntimeException(e);
@@ -604,8 +602,7 @@
@Nullable
public LeaseInfo getLeaseInfo(@NonNull BlobHandle blobHandle) throws IOException {
try {
- return mService.getLeaseInfo(blobHandle, mContext.getOpPackageName(),
- mContext.getAttributionTag());
+ return mService.getLeaseInfo(blobHandle, mContext.getOpPackageName());
} catch (ParcelableException e) {
e.maybeRethrow(IOException.class);
throw new RuntimeException(e);
@@ -900,64 +897,6 @@
}
/**
- * Allow apps with location permission to access this blob data once it is committed using
- * a {@link BlobHandle} representing the blob.
- *
- * <p> This needs to be called before committing the blob using
- * {@link #commit(Executor, Consumer)}.
- *
- * Note that if a caller allows access to the blob using this API in addition to other APIs
- * like {@link #allowPackageAccess(String, byte[])}, then apps satisfying any one of these
- * access conditions will be allowed to access the blob.
- *
- * @param permissionName the name of the location permission that needs to be granted
- * for the app. This can be either one of
- * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} or
- * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}.
- *
- * @throws IOException when there is an I/O error while changing the access.
- * @throws SecurityException when the caller is not the owner of the session.
- * @throws IllegalStateException when the caller tries to change access for a blob which is
- * already committed.
- */
- public void allowPackagesWithLocationPermission(@NonNull String permissionName)
- throws IOException {
- try {
- mSession.allowPackagesWithLocationPermission(permissionName);
- } catch (ParcelableException e) {
- e.maybeRethrow(IOException.class);
- throw new RuntimeException(e);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Returns {@code true} if access has been allowed for apps with location permission by
- * using {@link #allowPackagesWithLocationPermission(String)}.
- *
- * @param permissionName the name of the location permission that needs to be granted
- * for the app. This can be either one of
- * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} or
- * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}.
- *
- * @throws IOException when there is an I/O error while getting the access type.
- * @throws IllegalStateException when the caller tries to get access type from a session
- * which is closed or abandoned.
- */
- public boolean arePackagesWithLocationPermissionAllowed(@NonNull String permissionName)
- throws IOException {
- try {
- return mSession.arePackagesWithLocationPermissionAllowed(permissionName);
- } catch (ParcelableException e) {
- e.maybeRethrow(IOException.class);
- throw new RuntimeException(e);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
* Commit the file that was written so far to this session to the blob store maintained by
* the system.
*
diff --git a/apex/blobstore/framework/java/android/app/blob/IBlobStoreManager.aidl b/apex/blobstore/framework/java/android/app/blob/IBlobStoreManager.aidl
index db6cb5c9..39a9fb4 100644
--- a/apex/blobstore/framework/java/android/app/blob/IBlobStoreManager.aidl
+++ b/apex/blobstore/framework/java/android/app/blob/IBlobStoreManager.aidl
@@ -25,13 +25,12 @@
interface IBlobStoreManager {
long createSession(in BlobHandle handle, in String packageName);
IBlobStoreSession openSession(long sessionId, in String packageName);
- ParcelFileDescriptor openBlob(in BlobHandle handle, in String packageName,
- in String attributionTag);
+ ParcelFileDescriptor openBlob(in BlobHandle handle, in String packageName);
void abandonSession(long sessionId, in String packageName);
void acquireLease(in BlobHandle handle, int descriptionResId, in CharSequence description,
- long leaseTimeoutMillis, in String packageName, in String attributionTag);
- void releaseLease(in BlobHandle handle, in String packageName, in String attributionTag);
+ long leaseTimeoutMillis, in String packageName);
+ void releaseLease(in BlobHandle handle, in String packageName);
long getRemainingLeaseQuotaBytes(String packageName);
void waitForIdle(in RemoteCallback callback);
@@ -40,6 +39,5 @@
void deleteBlob(long blobId);
List<BlobHandle> getLeasedBlobs(in String packageName);
- LeaseInfo getLeaseInfo(in BlobHandle blobHandle, in String packageName,
- in String attributionTag);
+ LeaseInfo getLeaseInfo(in BlobHandle blobHandle, in String packageName);
}
\ No newline at end of file
diff --git a/apex/blobstore/framework/java/android/app/blob/IBlobStoreSession.aidl b/apex/blobstore/framework/java/android/app/blob/IBlobStoreSession.aidl
index e3ccfb8..4035b96 100644
--- a/apex/blobstore/framework/java/android/app/blob/IBlobStoreSession.aidl
+++ b/apex/blobstore/framework/java/android/app/blob/IBlobStoreSession.aidl
@@ -26,12 +26,10 @@
void allowPackageAccess(in String packageName, in byte[] certificate);
void allowSameSignatureAccess();
void allowPublicAccess();
- void allowPackagesWithLocationPermission(in String permissionName);
boolean isPackageAccessAllowed(in String packageName, in byte[] certificate);
boolean isSameSignatureAccessAllowed();
boolean isPublicAccessAllowed();
- boolean arePackagesWithLocationPermissionAllowed(in String permissionName);
long getSize();
void close();
diff --git a/apex/blobstore/framework/java/android/app/blob/XmlTags.java b/apex/blobstore/framework/java/android/app/blob/XmlTags.java
index 6e4b2f7..bfc5826 100644
--- a/apex/blobstore/framework/java/android/app/blob/XmlTags.java
+++ b/apex/blobstore/framework/java/android/app/blob/XmlTags.java
@@ -38,7 +38,6 @@
public static final String ATTR_TYPE = "t";
public static final String TAG_ALLOWED_PACKAGE = "wl";
public static final String ATTR_CERTIFICATE = "ct";
- public static final String TAG_ALLOWED_PERMISSION = "ap";
// For BlobHandle
public static final String TAG_BLOB_HANDLE = "bh";
@@ -56,7 +55,4 @@
public static final String TAG_LEASEE = "l";
public static final String ATTR_DESCRIPTION_RES_NAME = "rn";
public static final String ATTR_DESCRIPTION = "d";
-
- // Generic
- public static final String ATTR_VALUE = "val";
}
diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobAccessMode.java b/apex/blobstore/service/java/com/android/server/blob/BlobAccessMode.java
index 09260b7..0d17bbc 100644
--- a/apex/blobstore/service/java/com/android/server/blob/BlobAccessMode.java
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobAccessMode.java
@@ -15,30 +15,19 @@
*/
package com.android.server.blob;
-import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
-import static android.Manifest.permission.ACCESS_FINE_LOCATION;
import static android.app.blob.XmlTags.ATTR_CERTIFICATE;
import static android.app.blob.XmlTags.ATTR_PACKAGE;
import static android.app.blob.XmlTags.ATTR_TYPE;
-import static android.app.blob.XmlTags.ATTR_VALUE;
import static android.app.blob.XmlTags.TAG_ALLOWED_PACKAGE;
-import static android.app.blob.XmlTags.TAG_ALLOWED_PERMISSION;
-
-import static com.android.server.blob.BlobStoreConfig.TAG;
import android.annotation.IntDef;
import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.app.AppOpsManager;
import android.content.Context;
import android.content.pm.PackageManager;
-import android.os.UserHandle;
-import android.permission.PermissionManager;
import android.util.ArraySet;
import android.util.Base64;
import android.util.DebugUtils;
import android.util.IndentingPrintWriter;
-import android.util.Slog;
import com.android.internal.util.XmlUtils;
@@ -64,27 +53,21 @@
ACCESS_TYPE_PUBLIC,
ACCESS_TYPE_SAME_SIGNATURE,
ACCESS_TYPE_ALLOWLIST,
- ACCESS_TYPE_LOCATION_PERMISSION,
})
@interface AccessType {}
public static final int ACCESS_TYPE_PRIVATE = 1 << 0;
public static final int ACCESS_TYPE_PUBLIC = 1 << 1;
public static final int ACCESS_TYPE_SAME_SIGNATURE = 1 << 2;
public static final int ACCESS_TYPE_ALLOWLIST = 1 << 3;
- public static final int ACCESS_TYPE_LOCATION_PERMISSION = 1 << 4;
private int mAccessType = ACCESS_TYPE_PRIVATE;
private final ArraySet<PackageIdentifier> mAllowedPackages = new ArraySet<>();
- private final ArraySet<String> mAllowedPermissions = new ArraySet<>();
void allow(BlobAccessMode other) {
if ((other.mAccessType & ACCESS_TYPE_ALLOWLIST) != 0) {
mAllowedPackages.addAll(other.mAllowedPackages);
}
- if ((other.mAccessType & ACCESS_TYPE_LOCATION_PERMISSION) != 0) {
- mAllowedPermissions.addAll(other.mAllowedPermissions);
- }
mAccessType |= other.mAccessType;
}
@@ -101,11 +84,6 @@
mAllowedPackages.add(PackageIdentifier.create(packageName, certificate));
}
- void allowPackagesWithLocationPermission(@NonNull String permissionName) {
- mAccessType |= ACCESS_TYPE_LOCATION_PERMISSION;
- mAllowedPermissions.add(permissionName);
- }
-
boolean isPublicAccessAllowed() {
return (mAccessType & ACCESS_TYPE_PUBLIC) != 0;
}
@@ -121,15 +99,8 @@
return mAllowedPackages.contains(PackageIdentifier.create(packageName, certificate));
}
- boolean arePackagesWithLocationPermissionAllowed(@NonNull String permissionName) {
- if ((mAccessType & ACCESS_TYPE_LOCATION_PERMISSION) == 0) {
- return false;
- }
- return mAllowedPermissions.contains(permissionName);
- }
-
- boolean isAccessAllowedForCaller(Context context, @NonNull String callingPackage,
- @NonNull String committerPackage, int callingUid, @Nullable String attributionTag) {
+ boolean isAccessAllowedForCaller(Context context,
+ @NonNull String callingPackage, @NonNull String committerPackage) {
if ((mAccessType & ACCESS_TYPE_PUBLIC) != 0) {
return true;
}
@@ -153,37 +124,9 @@
}
}
- if ((mAccessType & ACCESS_TYPE_LOCATION_PERMISSION) != 0) {
- final AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class);
- for (int i = 0; i < mAllowedPermissions.size(); ++i) {
- final String permission = mAllowedPermissions.valueAt(i);
- if (PermissionManager.checkPackageNamePermission(permission, callingPackage,
- UserHandle.getUserId(callingUid)) != PackageManager.PERMISSION_GRANTED) {
- continue;
- }
- // TODO: Add appropriate message
- if (appOpsManager.noteOpNoThrow(getAppOp(permission), callingUid, callingPackage,
- attributionTag, null /* message */) == AppOpsManager.MODE_ALLOWED) {
- return true;
- }
- }
- }
-
return false;
}
- private static String getAppOp(String permission) {
- switch (permission) {
- case ACCESS_FINE_LOCATION:
- return AppOpsManager.OPSTR_FINE_LOCATION;
- case ACCESS_COARSE_LOCATION:
- return AppOpsManager.OPSTR_COARSE_LOCATION;
- default:
- Slog.w(TAG, "Unknown permission found: " + permission);
- return null;
- }
- }
-
int getAccessType() {
return mAccessType;
}
@@ -205,16 +148,6 @@
}
fout.decreaseIndent();
}
- fout.print("Allowed permissions:");
- if (mAllowedPermissions.isEmpty()) {
- fout.println(" (Empty)");
- } else {
- fout.increaseIndent();
- for (int i = 0, count = mAllowedPermissions.size(); i < count; ++i) {
- fout.println(mAllowedPermissions.valueAt(i).toString());
- }
- fout.decreaseIndent();
- }
}
void writeToXml(@NonNull XmlSerializer out) throws IOException {
@@ -226,12 +159,6 @@
XmlUtils.writeByteArrayAttribute(out, ATTR_CERTIFICATE, packageIdentifier.certificate);
out.endTag(null, TAG_ALLOWED_PACKAGE);
}
- for (int i = 0, count = mAllowedPermissions.size(); i < count; ++i) {
- out.startTag(null, TAG_ALLOWED_PERMISSION);
- final String permission = mAllowedPermissions.valueAt(i);
- XmlUtils.writeStringAttribute(out, ATTR_VALUE, permission);
- out.endTag(null, TAG_ALLOWED_PERMISSION);
- }
}
@NonNull
@@ -249,10 +176,6 @@
final byte[] certificate = XmlUtils.readByteArrayAttribute(in, ATTR_CERTIFICATE);
blobAccessMode.allowPackageAccess(packageName, certificate);
}
- if (TAG_ALLOWED_PERMISSION.equals(in.getName())) {
- final String permission = XmlUtils.readStringAttribute(in, ATTR_VALUE);
- blobAccessMode.allowPackagesWithLocationPermission(permission);
- }
}
return blobAccessMode;
}
diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobMetadata.java b/apex/blobstore/service/java/com/android/server/blob/BlobMetadata.java
index e477156..e116c81 100644
--- a/apex/blobstore/service/java/com/android/server/blob/BlobMetadata.java
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobMetadata.java
@@ -263,8 +263,7 @@
return getBlobFile().length();
}
- boolean isAccessAllowedForCaller(@NonNull String callingPackage, int callingUid,
- @Nullable String attributionTag) {
+ boolean isAccessAllowedForCaller(@NonNull String callingPackage, int callingUid) {
// Don't allow the blob to be accessed after it's expiry time has passed.
if (getBlobHandle().isExpired()) {
return false;
@@ -293,7 +292,7 @@
// Check if the caller is allowed access as per the access mode specified
// by the committer.
if (committer.blobAccessMode.isAccessAllowedForCaller(mContext,
- callingPackage, committer.packageName, callingUid, attributionTag)) {
+ callingPackage, committer.packageName)) {
return true;
}
}
@@ -316,7 +315,7 @@
// Check if the caller is allowed access as per the access mode specified
// by the committer.
if (committer.blobAccessMode.isAccessAllowedForCaller(mContext,
- callingPackage, committer.packageName, callingUid, attributionTag)) {
+ callingPackage, committer.packageName)) {
return true;
}
}
diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java b/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java
index 731ba92..beeffd6 100644
--- a/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java
@@ -397,11 +397,11 @@
}
private ParcelFileDescriptor openBlobInternal(BlobHandle blobHandle, int callingUid,
- String callingPackage, String attributionTag) throws IOException {
+ String callingPackage) throws IOException {
synchronized (mBlobsLock) {
final BlobMetadata blobMetadata = mBlobsMap.get(blobHandle);
if (blobMetadata == null || !blobMetadata.isAccessAllowedForCaller(
- callingPackage, callingUid, attributionTag)) {
+ callingPackage, callingUid)) {
if (blobMetadata == null) {
FrameworkStatsLog.write(FrameworkStatsLog.BLOB_OPENED, callingUid,
INVALID_BLOB_ID, INVALID_BLOB_SIZE,
@@ -449,7 +449,7 @@
private void acquireLeaseInternal(BlobHandle blobHandle, int descriptionResId,
CharSequence description, long leaseExpiryTimeMillis,
- int callingUid, String callingPackage, String attributionTag) {
+ int callingUid, String callingPackage) {
synchronized (mBlobsLock) {
final int leasesCount = getLeasedBlobsCountLocked(callingUid, callingPackage);
if (leasesCount >= getMaxLeasedBlobs()) {
@@ -470,7 +470,7 @@
final BlobMetadata blobMetadata = mBlobsMap.get(blobHandle);
if (blobMetadata == null || !blobMetadata.isAccessAllowedForCaller(
- callingPackage, callingUid, attributionTag)) {
+ callingPackage, callingUid)) {
if (blobMetadata == null) {
FrameworkStatsLog.write(FrameworkStatsLog.BLOB_LEASED, callingUid,
INVALID_BLOB_ID, INVALID_BLOB_SIZE,
@@ -521,11 +521,11 @@
}
private void releaseLeaseInternal(BlobHandle blobHandle, int callingUid,
- String callingPackage, String attributionTag) {
+ String callingPackage) {
synchronized (mBlobsLock) {
final BlobMetadata blobMetadata = mBlobsMap.get(blobHandle);
if (blobMetadata == null || !blobMetadata.isAccessAllowedForCaller(
- callingPackage, callingUid, attributionTag)) {
+ callingPackage, callingUid)) {
throw new SecurityException("Caller not allowed to access " + blobHandle
+ "; callingUid=" + callingUid + ", callingPackage=" + callingPackage);
}
@@ -632,11 +632,11 @@
}
private LeaseInfo getLeaseInfoInternal(BlobHandle blobHandle,
- int callingUid, @NonNull String callingPackage, String attributionTag) {
+ int callingUid, @NonNull String callingPackage) {
synchronized (mBlobsLock) {
final BlobMetadata blobMetadata = mBlobsMap.get(blobHandle);
if (blobMetadata == null || !blobMetadata.isAccessAllowedForCaller(
- callingPackage, callingUid, attributionTag)) {
+ callingPackage, callingUid)) {
throw new SecurityException("Caller not allowed to access " + blobHandle
+ "; callingUid=" + callingUid + ", callingPackage=" + callingPackage);
}
@@ -1478,7 +1478,7 @@
@Override
public ParcelFileDescriptor openBlob(@NonNull BlobHandle blobHandle,
- @NonNull String packageName, @Nullable String attributionTag) {
+ @NonNull String packageName) {
Objects.requireNonNull(blobHandle, "blobHandle must not be null");
blobHandle.assertIsValid();
Objects.requireNonNull(packageName, "packageName must not be null");
@@ -1493,7 +1493,7 @@
}
try {
- return openBlobInternal(blobHandle, callingUid, packageName, attributionTag);
+ return openBlobInternal(blobHandle, callingUid, packageName);
} catch (IOException e) {
throw ExceptionUtils.wrap(e);
}
@@ -1502,8 +1502,7 @@
@Override
public void acquireLease(@NonNull BlobHandle blobHandle, @IdRes int descriptionResId,
@Nullable CharSequence description,
- @CurrentTimeSecondsLong long leaseExpiryTimeMillis, @NonNull String packageName,
- @Nullable String attributionTag) {
+ @CurrentTimeSecondsLong long leaseExpiryTimeMillis, @NonNull String packageName) {
Objects.requireNonNull(blobHandle, "blobHandle must not be null");
blobHandle.assertIsValid();
Preconditions.checkArgument(
@@ -1527,7 +1526,7 @@
try {
acquireLeaseInternal(blobHandle, descriptionResId, description,
- leaseExpiryTimeMillis, callingUid, packageName, attributionTag);
+ leaseExpiryTimeMillis, callingUid, packageName);
} catch (Resources.NotFoundException e) {
throw new IllegalArgumentException(e);
} catch (LimitExceededException e) {
@@ -1536,8 +1535,7 @@
}
@Override
- public void releaseLease(@NonNull BlobHandle blobHandle, @NonNull String packageName,
- @Nullable String attributionTag) {
+ public void releaseLease(@NonNull BlobHandle blobHandle, @NonNull String packageName) {
Objects.requireNonNull(blobHandle, "blobHandle must not be null");
blobHandle.assertIsValid();
Objects.requireNonNull(packageName, "packageName must not be null");
@@ -1551,7 +1549,7 @@
+ "callingUid=" + callingUid + ", callingPackage=" + packageName);
}
- releaseLeaseInternal(blobHandle, callingUid, packageName, attributionTag);
+ releaseLeaseInternal(blobHandle, callingUid, packageName);
}
@Override
@@ -1621,8 +1619,7 @@
@Override
@Nullable
- public LeaseInfo getLeaseInfo(@NonNull BlobHandle blobHandle, @NonNull String packageName,
- @Nullable String attributionTag) {
+ public LeaseInfo getLeaseInfo(@NonNull BlobHandle blobHandle, @NonNull String packageName) {
Objects.requireNonNull(blobHandle, "blobHandle must not be null");
blobHandle.assertIsValid();
Objects.requireNonNull(packageName, "packageName must not be null");
@@ -1636,7 +1633,7 @@
+ "callingUid=" + callingUid + ", callingPackage=" + packageName);
}
- return getLeaseInfoInternal(blobHandle, callingUid, packageName, attributionTag);
+ return getLeaseInfoInternal(blobHandle, callingUid, packageName);
}
@Override
diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobStoreSession.java b/apex/blobstore/service/java/com/android/server/blob/BlobStoreSession.java
index 3f0032f..8eef8ce 100644
--- a/apex/blobstore/service/java/com/android/server/blob/BlobStoreSession.java
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobStoreSession.java
@@ -15,8 +15,6 @@
*/
package com.android.server.blob;
-import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
-import static android.Manifest.permission.ACCESS_FINE_LOCATION;
import static android.app.blob.BlobStoreManager.COMMIT_RESULT_ERROR;
import static android.app.blob.XmlTags.ATTR_CREATION_TIME_MS;
import static android.app.blob.XmlTags.ATTR_ID;
@@ -368,21 +366,6 @@
}
@Override
- public void allowPackagesWithLocationPermission(@NonNull String permissionName) {
- assertCallerIsOwner();
- Preconditions.checkArgument(ACCESS_FINE_LOCATION.equals(permissionName)
- || ACCESS_COARSE_LOCATION.equals(permissionName),
- "permissionName is unknown: " + permissionName);
- synchronized (mSessionLock) {
- if (mState != STATE_OPENED) {
- throw new IllegalStateException("Not allowed to change access type in state: "
- + stateToString(mState));
- }
- mBlobAccessMode.allowPackagesWithLocationPermission(permissionName);
- }
- }
-
- @Override
public boolean isPackageAccessAllowed(@NonNull String packageName,
@NonNull byte[] certificate) {
assertCallerIsOwner();
@@ -423,21 +406,6 @@
}
@Override
- public boolean arePackagesWithLocationPermissionAllowed(@NonNull String permissionName) {
- assertCallerIsOwner();
- Preconditions.checkArgument(ACCESS_FINE_LOCATION.equals(permissionName)
- || ACCESS_COARSE_LOCATION.equals(permissionName),
- "permissionName is unknown: " + permissionName);
- synchronized (mSessionLock) {
- if (mState != STATE_OPENED) {
- throw new IllegalStateException("Not allowed to change access type in state: "
- + stateToString(mState));
- }
- return mBlobAccessMode.arePackagesWithLocationPermissionAllowed(permissionName);
- }
- }
-
- @Override
public void close() {
closeSession(STATE_CLOSED, false /* sendCallback */);
}
diff --git a/apex/jobscheduler/framework/java/android/app/AlarmManager.java b/apex/jobscheduler/framework/java/android/app/AlarmManager.java
index 8b824e8..9fa7810 100644
--- a/apex/jobscheduler/framework/java/android/app/AlarmManager.java
+++ b/apex/jobscheduler/framework/java/android/app/AlarmManager.java
@@ -532,9 +532,10 @@
* modest timeliness requirements for its alarms.
*
* <p>
- * Note: Starting with API {@link Build.VERSION_CODES#S}, the system will ensure that the window
- * specified is at least a few minutes, as smaller windows are considered practically exact
- * and should use the other APIs provided for exact alarms.
+ * Note: Starting with API {@link Build.VERSION_CODES#S}, apps should not pass in a window of
+ * less than 10 minutes. The system will try its best to accommodate smaller windows if the
+ * alarm is supposed to fire in the near future, but there are no guarantees and the app should
+ * expect any window smaller than 10 minutes to get elongated to 10 minutes.
*
* <p>
* This method can also be used to achieve strict ordering guarantees among
@@ -588,9 +589,10 @@
* if {@code null} is passed as the {@code targetHandler} parameter.
*
* <p>
- * Note: Starting with API {@link Build.VERSION_CODES#S}, the system will ensure that the window
- * specified is at least a few minutes, as smaller windows are considered practically exact
- * and should use the other APIs provided for exact alarms.
+ * Note: Starting with API {@link Build.VERSION_CODES#S}, apps should not pass in a window of
+ * less than 10 minutes. The system will try its best to accommodate smaller windows if the
+ * alarm is supposed to fire in the near future, but there are no guarantees and the app should
+ * expect any window smaller than 10 minutes to get elongated to 10 minutes.
*
* @see #setWindow(int, long, long, PendingIntent)
*/
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 0eb2609..5365218 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
@@ -530,8 +530,7 @@
private static final long DEFAULT_MIN_FUTURITY = 5 * 1000;
private static final long DEFAULT_MIN_INTERVAL = 60 * 1000;
private static final long DEFAULT_MAX_INTERVAL = 365 * INTERVAL_DAY;
- // TODO (b/185199076): Tune based on breakage reports.
- private static final long DEFAULT_MIN_WINDOW = 30 * 60 * 1000;
+ private static final long DEFAULT_MIN_WINDOW = 10 * 60 * 1000;
private static final long DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION = 10 * 1000;
private static final long DEFAULT_LISTENER_TIMEOUT = 5 * 1000;
private static final int DEFAULT_MAX_ALARMS_PER_UID = 500;
@@ -1147,6 +1146,18 @@
return when;
}
+ /**
+ * This is the minimum window that can be requested for the given alarm. Windows smaller than
+ * this value will be elongated to match it.
+ * Current heuristic is similar to {@link #maxTriggerTime(long, long, long)}, the minimum
+ * allowed window is either {@link Constants#MIN_WINDOW} or 75% of the alarm's futurity,
+ * whichever is smaller.
+ */
+ long getMinimumAllowedWindow(long nowElapsed, long triggerElapsed) {
+ final long futurity = triggerElapsed - nowElapsed;
+ return Math.min((long) (futurity * 0.75), mConstants.MIN_WINDOW);
+ }
+
// Apply a heuristic to { recurrence interval, futurity of the trigger time } to
// calculate the end of our nominal delivery window for the alarm.
static long maxTriggerTime(long now, long triggerAtTime, long interval) {
@@ -1833,25 +1844,6 @@
}
}
- // Snap the window to reasonable limits.
- if (windowLength > INTERVAL_DAY) {
- Slog.w(TAG, "Window length " + windowLength
- + "ms suspiciously long; limiting to 1 day");
- windowLength = INTERVAL_DAY;
- } else if (windowLength > 0 && windowLength < mConstants.MIN_WINDOW
- && (flags & FLAG_PRIORITIZE) == 0) {
- if (CompatChanges.isChangeEnabled(AlarmManager.ENFORCE_MINIMUM_WINDOW_ON_INEXACT_ALARMS,
- callingPackage, UserHandle.getUserHandleForUid(callingUid))) {
- Slog.w(TAG, "Window length " + windowLength + "ms too short; expanding to "
- + mConstants.MIN_WINDOW + "ms.");
- windowLength = mConstants.MIN_WINDOW;
- } else {
- // TODO (b/185199076): Remove log once we have some data about what apps will break
- Slog.wtf(TAG, "Short window " + windowLength + "ms specified by "
- + callingPackage);
- }
- }
-
// Sanity check the recurrence interval. This will catch people who supply
// seconds when the API expects milliseconds, or apps trying shenanigans
// around intentional period overflow, etc.
@@ -1883,7 +1875,7 @@
// Try to prevent spamming by making sure apps aren't firing alarms in the immediate future
final long minTrigger = nowElapsed
+ (UserHandle.isCore(callingUid) ? 0L : mConstants.MIN_FUTURITY);
- final long triggerElapsed = (nominalTrigger > minTrigger) ? nominalTrigger : minTrigger;
+ final long triggerElapsed = Math.max(minTrigger, nominalTrigger);
final long maxElapsed;
if (windowLength == 0) {
@@ -1893,6 +1885,25 @@
// Fix this window in place, so that as time approaches we don't collapse it.
windowLength = maxElapsed - triggerElapsed;
} else {
+ // The window was explicitly requested. Snap it to allowable limits.
+ final long minAllowedWindow = getMinimumAllowedWindow(nowElapsed, triggerElapsed);
+ if (windowLength > INTERVAL_DAY) {
+ Slog.w(TAG, "Window length " + windowLength + "ms too long; limiting to 1 day");
+ windowLength = INTERVAL_DAY;
+ } else if ((flags & FLAG_PRIORITIZE) == 0 && windowLength < minAllowedWindow) {
+ // Prioritized alarms are exempt from minimum window limits.
+ if (CompatChanges.isChangeEnabled(
+ AlarmManager.ENFORCE_MINIMUM_WINDOW_ON_INEXACT_ALARMS, callingPackage,
+ UserHandle.getUserHandleForUid(callingUid))) {
+ Slog.w(TAG, "Window length " + windowLength + "ms too short; expanding to "
+ + minAllowedWindow + "ms.");
+ windowLength = minAllowedWindow;
+ } else {
+ // TODO (b/185199076): Remove temporary log to catch breaking apps.
+ Slog.wtf(TAG, "Short window " + windowLength + "ms specified by "
+ + callingPackage);
+ }
+ }
maxElapsed = triggerElapsed + windowLength;
}
synchronized (mLock) {
diff --git a/api/Android.bp b/api/Android.bp
index db1f64c..b85dc46 100644
--- a/api/Android.bp
+++ b/api/Android.bp
@@ -161,7 +161,6 @@
genrule {
name: "frameworks-base-api-system-current.txt",
srcs: [
- ":art.module.public.api{.system.api.txt}",
":android.net.ipsec.ike{.system.api.txt}",
":framework-appsearch{.system.api.txt}",
":framework-connectivity{.system.api.txt}",
@@ -216,7 +215,6 @@
genrule {
name: "frameworks-base-api-system-removed.txt",
srcs: [
- ":art.module.public.api{.system.removed-api.txt}",
":android.net.ipsec.ike{.system.removed-api.txt}",
":framework-appsearch{.system.removed-api.txt}",
":framework-connectivity{.system.removed-api.txt}",
@@ -253,7 +251,6 @@
genrule {
name: "frameworks-base-api-module-lib-current.txt",
srcs: [
- ":art.module.public.api{.module-lib.api.txt}",
":android.net.ipsec.ike{.module-lib.api.txt}",
":framework-appsearch{.module-lib.api.txt}",
":framework-connectivity{.module-lib.api.txt}",
@@ -310,7 +307,6 @@
genrule {
name: "frameworks-base-api-module-lib-removed.txt",
srcs: [
- ":art.module.public.api{.module-lib.removed-api.txt}",
":android.net.ipsec.ike{.module-lib.removed-api.txt}",
":framework-appsearch{.module-lib.removed-api.txt}",
":framework-connectivity{.module-lib.removed-api.txt}",
diff --git a/cmds/sm/src/com/android/commands/sm/Sm.java b/cmds/sm/src/com/android/commands/sm/Sm.java
index f5bee6c..260c8a4 100644
--- a/cmds/sm/src/com/android/commands/sm/Sm.java
+++ b/cmds/sm/src/com/android/commands/sm/Sm.java
@@ -258,7 +258,7 @@
public void runDisableAppDataIsolation() throws RemoteException {
if (!SystemProperties.getBoolean(
- ANDROID_VOLD_APP_DATA_ISOLATION_ENABLED_PROPERTY, true)) {
+ ANDROID_VOLD_APP_DATA_ISOLATION_ENABLED_PROPERTY, false)) {
throw new IllegalStateException("Storage app data isolation is not enabled.");
}
final String pkgName = nextArg();
diff --git a/core/api/current.txt b/core/api/current.txt
index 6d0d344..0bf47de 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -141,6 +141,7 @@
field public static final String REORDER_TASKS = "android.permission.REORDER_TASKS";
field public static final String REQUEST_COMPANION_PROFILE_WATCH = "android.permission.REQUEST_COMPANION_PROFILE_WATCH";
field public static final String REQUEST_COMPANION_RUN_IN_BACKGROUND = "android.permission.REQUEST_COMPANION_RUN_IN_BACKGROUND";
+ field public static final String REQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND = "android.permission.REQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND";
field public static final String REQUEST_COMPANION_USE_DATA_IN_BACKGROUND = "android.permission.REQUEST_COMPANION_USE_DATA_IN_BACKGROUND";
field public static final String REQUEST_DELETE_PACKAGES = "android.permission.REQUEST_DELETE_PACKAGES";
field public static final String REQUEST_IGNORE_BATTERY_OPTIMIZATIONS = "android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS";
@@ -3173,6 +3174,7 @@
field public static final int FLAG_ENABLE_ACCESSIBILITY_VOLUME = 128; // 0x80
field public static final int FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 2; // 0x2
field public static final int FLAG_REPORT_VIEW_IDS = 16; // 0x10
+ field public static final int FLAG_REQUEST_2_FINGER_PASSTHROUGH = 8192; // 0x2000
field public static final int FLAG_REQUEST_ACCESSIBILITY_BUTTON = 256; // 0x100
field @Deprecated public static final int FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 8; // 0x8
field public static final int FLAG_REQUEST_FILTER_KEY_EVENTS = 32; // 0x20
@@ -7904,10 +7906,8 @@
public static class BlobStoreManager.Session implements java.io.Closeable {
method public void abandon() throws java.io.IOException;
method public void allowPackageAccess(@NonNull String, @NonNull byte[]) throws java.io.IOException;
- method public void allowPackagesWithLocationPermission(@NonNull String) throws java.io.IOException;
method public void allowPublicAccess() throws java.io.IOException;
method public void allowSameSignatureAccess() throws java.io.IOException;
- method public boolean arePackagesWithLocationPermissionAllowed(@NonNull String) throws java.io.IOException;
method public void close() throws java.io.IOException;
method public void commit(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>) throws java.io.IOException;
method public long getSize() throws java.io.IOException;
@@ -9040,7 +9040,7 @@
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public String getName();
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getType();
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.os.ParcelUuid[] getUuids();
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean setAlias(@NonNull String);
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int setAlias(@Nullable String);
method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setPairingConfirmation(boolean);
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean setPin(byte[]);
method public void writeToParcel(android.os.Parcel, int);
@@ -9488,6 +9488,15 @@
field public static final int TYPE_SCO = 2; // 0x2
}
+ public final class BluetoothStatusCodes {
+ field public static final int ERROR_BLUETOOTH_NOT_ALLOWED = 2; // 0x2
+ field public static final int ERROR_BLUETOOTH_NOT_ENABLED = 1; // 0x1
+ field public static final int ERROR_DEVICE_NOT_BONDED = 3; // 0x3
+ field public static final int ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION = 6; // 0x6
+ field public static final int ERROR_UNKNOWN = 2147483647; // 0x7fffffff
+ field public static final int SUCCESS = 0; // 0x0
+ }
+
}
package android.bluetooth.le {
@@ -11881,7 +11890,6 @@
field public static final int SCREEN_ORIENTATION_USER_LANDSCAPE = 11; // 0xb
field public static final int SCREEN_ORIENTATION_USER_PORTRAIT = 12; // 0xc
field public static final int UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW = 1; // 0x1
- field public String[] attributionTags;
field public int colorMode;
field public int configChanges;
field public int documentLaunchMode;
@@ -12073,6 +12081,7 @@
method public final int getLogoResource();
method public boolean isEnabled();
field public android.content.pm.ApplicationInfo applicationInfo;
+ field public String[] attributionTags;
field public int descriptionRes;
field public boolean directBootAware;
field public boolean enabled;
@@ -31949,6 +31958,7 @@
method public long getUserCreationTime(android.os.UserHandle);
method public android.os.UserHandle getUserForSerialNumber(long);
method @NonNull @RequiresPermission(anyOf={"android.permission.MANAGE_USERS", android.Manifest.permission.GET_ACCOUNTS_PRIVILEGED, "android.permission.CREATE_USERS"}, conditional=true) public String getUserName();
+ method public int getUserPrivacySensitivity();
method public java.util.List<android.os.UserHandle> getUserProfiles();
method public android.os.Bundle getUserRestrictions();
method @RequiresPermission(anyOf={"android.permission.MANAGE_USERS", "android.permission.INTERACT_ACROSS_USERS"}, conditional=true) public android.os.Bundle getUserRestrictions(android.os.UserHandle);
@@ -31981,6 +31991,7 @@
field public static final String DISALLOW_AUTOFILL = "no_autofill";
field public static final String DISALLOW_BLUETOOTH = "no_bluetooth";
field public static final String DISALLOW_BLUETOOTH_SHARING = "no_bluetooth_sharing";
+ field public static final String DISALLOW_CAMERA_TOGGLE = "disallow_camera_toggle";
field public static final String DISALLOW_CONFIG_BLUETOOTH = "no_config_bluetooth";
field public static final String DISALLOW_CONFIG_BRIGHTNESS = "no_config_brightness";
field public static final String DISALLOW_CONFIG_CELL_BROADCASTS = "no_config_cell_broadcasts";
@@ -32005,6 +32016,7 @@
field public static final String DISALLOW_INSTALL_APPS = "no_install_apps";
field public static final String DISALLOW_INSTALL_UNKNOWN_SOURCES = "no_install_unknown_sources";
field public static final String DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY = "no_install_unknown_sources_globally";
+ field public static final String DISALLOW_MICROPHONE_TOGGLE = "disallow_microphone_toggle";
field public static final String DISALLOW_MODIFY_ACCOUNTS = "no_modify_accounts";
field public static final String DISALLOW_MOUNT_PHYSICAL_MEDIA = "no_physical_media";
field public static final String DISALLOW_NETWORK_RESET = "no_network_reset";
@@ -32027,6 +32039,8 @@
field public static final String DISALLOW_USER_SWITCH = "no_user_switch";
field public static final String ENSURE_VERIFY_APPS = "ensure_verify_apps";
field public static final String KEY_RESTRICTIONS_PENDING = "restrictions_pending";
+ field public static final int PRIVACY_SENSITIVITY_DEFAULT = 0; // 0x0
+ field public static final int PRIVACY_SENSITIVITY_LOCATION = 1; // 0x1
field public static final int QUIET_MODE_DISABLE_ONLY_IF_CREDENTIAL_NOT_REQUIRED = 1; // 0x1
field public static final int USER_CREATION_FAILED_NOT_PERMITTED = 1; // 0x1
field public static final int USER_CREATION_FAILED_NO_MORE_USERS = 2; // 0x2
@@ -39224,7 +39238,8 @@
method @MainThread public static android.speech.SpeechRecognizer createSpeechRecognizer(android.content.Context);
method @MainThread public static android.speech.SpeechRecognizer createSpeechRecognizer(android.content.Context, android.content.ComponentName);
method public void destroy();
- method public static boolean isRecognitionAvailable(android.content.Context);
+ method public static boolean isOnDeviceRecognitionAvailable(@NonNull android.content.Context);
+ method public static boolean isRecognitionAvailable(@NonNull android.content.Context);
method @MainThread public void setRecognitionListener(android.speech.RecognitionListener);
method @MainThread public void startListening(android.content.Intent);
method @MainThread public void stopListening();
@@ -51416,7 +51431,6 @@
public final class AutofillManager {
method public void cancel();
- method public void clearAutofillRequestCallback();
method public void commit();
method public void disableAutofillServices();
method @Nullable public android.content.ComponentName getAutofillServiceComponentName();
@@ -51442,7 +51456,6 @@
method public void registerCallback(@Nullable android.view.autofill.AutofillManager.AutofillCallback);
method public void requestAutofill(@NonNull android.view.View);
method public void requestAutofill(@NonNull android.view.View, int, @NonNull android.graphics.Rect);
- method public void setAutofillRequestCallback(@NonNull java.util.concurrent.Executor, @NonNull android.view.autofill.AutofillRequestCallback);
method public void setUserData(@Nullable android.service.autofill.UserData);
method public void unregisterCallback(@Nullable android.view.autofill.AutofillManager.AutofillCallback);
field public static final String EXTRA_ASSIST_STRUCTURE = "android.view.autofill.extra.ASSIST_STRUCTURE";
@@ -51461,10 +51474,6 @@
field public static final int EVENT_INPUT_UNAVAILABLE = 3; // 0x3
}
- public interface AutofillRequestCallback {
- method public void onFillRequest(@Nullable android.view.inputmethod.InlineSuggestionsRequest, @NonNull android.os.CancellationSignal, @NonNull android.service.autofill.FillCallback);
- }
-
public final class AutofillValue implements android.os.Parcelable {
method public int describeContents();
method public static android.view.autofill.AutofillValue forDate(long);
@@ -51835,12 +51844,10 @@
ctor public InlineSuggestionsRequest.Builder(@NonNull java.util.List<android.widget.inline.InlinePresentationSpec>);
method @NonNull public android.view.inputmethod.InlineSuggestionsRequest.Builder addInlinePresentationSpecs(@NonNull android.widget.inline.InlinePresentationSpec);
method @NonNull public android.view.inputmethod.InlineSuggestionsRequest build();
- method @NonNull public android.view.inputmethod.InlineSuggestionsRequest.Builder setClientSupported(boolean);
method @NonNull public android.view.inputmethod.InlineSuggestionsRequest.Builder setExtras(@NonNull android.os.Bundle);
method @NonNull public android.view.inputmethod.InlineSuggestionsRequest.Builder setInlinePresentationSpecs(@NonNull java.util.List<android.widget.inline.InlinePresentationSpec>);
method @NonNull public android.view.inputmethod.InlineSuggestionsRequest.Builder setInlineTooltipPresentationSpec(@NonNull android.widget.inline.InlinePresentationSpec);
method @NonNull public android.view.inputmethod.InlineSuggestionsRequest.Builder setMaxSuggestionCount(int);
- method @NonNull public android.view.inputmethod.InlineSuggestionsRequest.Builder setServiceSupported(boolean);
method @NonNull public android.view.inputmethod.InlineSuggestionsRequest.Builder setSupportedLocales(@NonNull android.os.LocaleList);
}
@@ -51983,6 +51990,7 @@
method public int getSubtypeCount();
method public android.graphics.drawable.Drawable loadIcon(android.content.pm.PackageManager);
method public CharSequence loadLabel(android.content.pm.PackageManager);
+ method public boolean shouldShowInInputMethodPicker();
method public boolean suppressesSpellChecker();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.view.inputmethod.InputMethodInfo> CREATOR;
@@ -52846,7 +52854,7 @@
method public int getTranslationFlags();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.view.translation.TranslationContext> CREATOR;
- field public static final int FLAG_DICTIONARY_DESCRIPTION = 4; // 0x4
+ field public static final int FLAG_DEFINITIONS = 4; // 0x4
field public static final int FLAG_LOW_LATENCY = 1; // 0x1
field public static final int FLAG_TRANSLITERATION = 2; // 0x2
}
@@ -52888,8 +52896,8 @@
public static final class TranslationRequest.Builder {
ctor public TranslationRequest.Builder();
- method @NonNull public android.view.translation.TranslationRequest.Builder addTranslationRequestValue(@NonNull android.view.translation.TranslationRequestValue);
- method @NonNull public android.view.translation.TranslationRequest.Builder addViewTranslationRequest(@NonNull android.view.translation.ViewTranslationRequest);
+ method @Deprecated @NonNull public android.view.translation.TranslationRequest.Builder addTranslationRequestValue(@NonNull android.view.translation.TranslationRequestValue);
+ method @Deprecated @NonNull public android.view.translation.TranslationRequest.Builder addViewTranslationRequest(@NonNull android.view.translation.ViewTranslationRequest);
method @NonNull public android.view.translation.TranslationRequest build();
method @NonNull public android.view.translation.TranslationRequest.Builder setFlags(int);
method @NonNull public android.view.translation.TranslationRequest.Builder setTranslationRequestValues(@NonNull java.util.List<android.view.translation.TranslationRequestValue>);
@@ -52899,7 +52907,7 @@
public final class TranslationRequestValue implements android.os.Parcelable {
method public int describeContents();
method @NonNull public static android.view.translation.TranslationRequestValue forText(@NonNull CharSequence);
- method @NonNull public CharSequence getText();
+ method @Nullable public CharSequence getText();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.view.translation.TranslationRequestValue> CREATOR;
}
@@ -52931,12 +52939,13 @@
public final class TranslationResponseValue implements android.os.Parcelable {
method public int describeContents();
method @NonNull public static android.view.translation.TranslationResponseValue forError();
- method @Nullable public CharSequence getDictionaryDescription();
+ method @NonNull public android.os.Bundle getExtras();
method public int getStatusCode();
method @Nullable public CharSequence getText();
method @Nullable public CharSequence getTransliteration();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.view.translation.TranslationResponseValue> CREATOR;
+ field public static final String EXTRA_DEFINITIONS = "android.view.translation.extra.DEFINITIONS";
field public static final int STATUS_ERROR = 1; // 0x1
field public static final int STATUS_SUCCESS = 0; // 0x0
}
@@ -52944,7 +52953,7 @@
public static final class TranslationResponseValue.Builder {
ctor public TranslationResponseValue.Builder(int);
method @NonNull public android.view.translation.TranslationResponseValue build();
- method @NonNull public android.view.translation.TranslationResponseValue.Builder setDictionaryDescription(@NonNull CharSequence);
+ method @NonNull public android.view.translation.TranslationResponseValue.Builder setExtras(@NonNull android.os.Bundle);
method @NonNull public android.view.translation.TranslationResponseValue.Builder setText(@NonNull CharSequence);
method @NonNull public android.view.translation.TranslationResponseValue.Builder setTransliteration(@NonNull CharSequence);
}
@@ -52976,7 +52985,7 @@
method public void onFinished();
method public void onPaused();
method public default void onResumed(@NonNull android.icu.util.ULocale, @NonNull android.icu.util.ULocale);
- method @Deprecated public void onStarted(@NonNull String, @NonNull String);
+ method @Deprecated public default void onStarted(@NonNull String, @NonNull String);
method public default void onStarted(@NonNull android.icu.util.ULocale, @NonNull android.icu.util.ULocale);
}
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index d30d59f..143d674b 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -211,6 +211,7 @@
field public static final String READ_CONTENT_RATING_SYSTEMS = "android.permission.READ_CONTENT_RATING_SYSTEMS";
field public static final String READ_DEVICE_CONFIG = "android.permission.READ_DEVICE_CONFIG";
field public static final String READ_DREAM_STATE = "android.permission.READ_DREAM_STATE";
+ field public static final String READ_GLOBAL_APP_SEARCH_DATA = "android.permission.READ_GLOBAL_APP_SEARCH_DATA";
field public static final String READ_INSTALL_SESSIONS = "android.permission.READ_INSTALL_SESSIONS";
field public static final String READ_NETWORK_USAGE_HISTORY = "android.permission.READ_NETWORK_USAGE_HISTORY";
field public static final String READ_OEM_UNLOCK_STATE = "android.permission.READ_OEM_UNLOCK_STATE";
@@ -317,7 +318,6 @@
public static final class R.attr {
field public static final int allowClearUserDataOnFailedRestore = 16844288; // 0x1010600
- field public static final int durationBetweenRequestsMillis;
field public static final int hotwordDetectionService;
field public static final int isVrOnly = 16844152; // 0x1010578
field public static final int minExtensionVersion = 16844305; // 0x1010611
@@ -1950,9 +1950,6 @@
field public static final int ACTIVE_DEVICE_ALL = 2; // 0x2
field public static final int ACTIVE_DEVICE_AUDIO = 0; // 0x0
field public static final int ACTIVE_DEVICE_PHONE_CALL = 1; // 0x1
- field public static final int OOB_ERROR_ADAPTER_DISABLED = 2; // 0x2
- field public static final int OOB_ERROR_ANOTHER_ACTIVE_REQUEST = 1; // 0x1
- field public static final int OOB_ERROR_UNKNOWN = 0; // 0x0
}
public static interface BluetoothAdapter.OnMetadataChangedListener {
@@ -2090,6 +2087,10 @@
field @Deprecated public static final int PRIORITY_ON = 100; // 0x64
}
+ public final class BluetoothStatusCodes {
+ field public static final int ERROR_ANOTHER_ACTIVE_OOB_REQUEST = 1000; // 0x3e8
+ }
+
public final class BluetoothUuid {
method public static boolean containsAnyUuid(@Nullable android.os.ParcelUuid[], @Nullable android.os.ParcelUuid[]);
method @NonNull public static android.os.ParcelUuid parseUuidFrom(@Nullable byte[]);
@@ -2245,7 +2246,7 @@
public final class CompanionDeviceManager {
method @RequiresPermission(android.Manifest.permission.ASSOCIATE_COMPANION_DEVICES) public void associate(@NonNull String, @NonNull android.net.MacAddress);
- method @RequiresPermission("android.permission.MANAGE_COMPANION_DEVICES") public boolean canPairWithoutPrompt(@NonNull String, @NonNull String, int);
+ method @RequiresPermission("android.permission.MANAGE_COMPANION_DEVICES") public boolean canPairWithoutPrompt(@NonNull String, @NonNull String, @NonNull android.os.UserHandle);
method @RequiresPermission("android.permission.MANAGE_COMPANION_DEVICES") public boolean isDeviceAssociatedForWifiConnection(@NonNull String, @NonNull android.net.MacAddress, @NonNull android.os.UserHandle);
}
@@ -4996,11 +4997,15 @@
public final class SatellitePvt implements android.os.Parcelable {
method public int describeContents();
- method @NonNull public android.location.SatellitePvt.ClockInfo getClockInfo();
+ method @Nullable public android.location.SatellitePvt.ClockInfo getClockInfo();
+ method public int getFlags();
method @FloatRange public double getIonoDelayMeters();
- method @NonNull public android.location.SatellitePvt.PositionEcef getPositionEcef();
+ method @Nullable public android.location.SatellitePvt.PositionEcef getPositionEcef();
method @FloatRange public double getTropoDelayMeters();
- method @NonNull public android.location.SatellitePvt.VelocityEcef getVelocityEcef();
+ method @Nullable public android.location.SatellitePvt.VelocityEcef getVelocityEcef();
+ method public boolean hasIono();
+ method public boolean hasPositionVelocityClockInfo();
+ method public boolean hasTropo();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.location.SatellitePvt> CREATOR;
}
@@ -5009,6 +5014,7 @@
ctor public SatellitePvt.Builder();
method @NonNull public android.location.SatellitePvt build();
method @NonNull public android.location.SatellitePvt.Builder setClockInfo(@NonNull android.location.SatellitePvt.ClockInfo);
+ method @NonNull public android.location.SatellitePvt.Builder setFlags(int);
method @NonNull public android.location.SatellitePvt.Builder setIonoDelayMeters(@FloatRange double);
method @NonNull public android.location.SatellitePvt.Builder setPositionEcef(@NonNull android.location.SatellitePvt.PositionEcef);
method @NonNull public android.location.SatellitePvt.Builder setTropoDelayMeters(@FloatRange double);
@@ -9888,9 +9894,9 @@
method @NonNull public final android.os.IBinder onBind(@NonNull android.content.Intent);
method public abstract void onGenerateDisplayHash(@NonNull byte[], @NonNull android.hardware.HardwareBuffer, @NonNull android.graphics.Rect, @NonNull String, @NonNull android.view.displayhash.DisplayHashResultCallback);
method @NonNull public abstract java.util.Map<java.lang.String,android.service.displayhash.DisplayHashParams> onGetDisplayHashAlgorithms();
+ method public abstract int onGetIntervalBetweenRequestsMillis();
method @Nullable public abstract android.view.displayhash.VerifiedDisplayHash onVerifyDisplayHash(@NonNull byte[], @NonNull android.view.displayhash.DisplayHash);
field public static final String SERVICE_INTERFACE = "android.service.displayhash.DisplayHashingService";
- field public static final String SERVICE_META_DATA = "android.displayhash.display_hashing_service";
}
}
@@ -10405,19 +10411,20 @@
method @Nullable public final android.os.IBinder onBind(@NonNull android.content.Intent);
method public void onConnected();
method public void onCreateTranslationSession(@NonNull android.view.translation.TranslationContext, int, @NonNull java.util.function.Consumer<java.lang.Boolean>);
- method @Deprecated public abstract void onCreateTranslationSession(@NonNull android.view.translation.TranslationContext, int);
+ method @Deprecated public void onCreateTranslationSession(@NonNull android.view.translation.TranslationContext, int);
method public void onDisconnected();
method public abstract void onFinishTranslationSession(int);
method public abstract void onTranslationCapabilitiesRequest(int, int, @NonNull java.util.function.Consumer<java.util.Set<android.view.translation.TranslationCapability>>);
- method public abstract void onTranslationRequest(@NonNull android.view.translation.TranslationRequest, int, @Nullable android.os.CancellationSignal, @NonNull android.service.translation.TranslationService.OnTranslationResultCallback);
+ method @Deprecated public void onTranslationRequest(@NonNull android.view.translation.TranslationRequest, int, @Nullable android.os.CancellationSignal, @NonNull android.service.translation.TranslationService.OnTranslationResultCallback);
+ method public void onTranslationRequest(@NonNull android.view.translation.TranslationRequest, int, @Nullable android.os.CancellationSignal, @NonNull java.util.function.Consumer<android.view.translation.TranslationResponse>);
method public final void updateTranslationCapability(@NonNull android.view.translation.TranslationCapability);
field public static final String SERVICE_INTERFACE = "android.service.translation.TranslationService";
field public static final String SERVICE_META_DATA = "android.translation_service";
}
- public static interface TranslationService.OnTranslationResultCallback {
+ @Deprecated public static interface TranslationService.OnTranslationResultCallback {
method @Deprecated public void onError();
- method public void onTranslationSuccess(@NonNull android.view.translation.TranslationResponse);
+ method @Deprecated public void onTranslationSuccess(@NonNull android.view.translation.TranslationResponse);
}
}
@@ -10539,6 +10546,7 @@
public abstract class HotwordDetectionService extends android.app.Service {
ctor public HotwordDetectionService();
+ method public static int getMaxCustomInitializationStatus();
method @Nullable public final android.os.IBinder onBind(@NonNull android.content.Intent);
method @Deprecated public void onDetect(@NonNull android.os.ParcelFileDescriptor, @NonNull android.media.AudioFormat, long, @NonNull android.service.voice.HotwordDetectionService.Callback);
method public void onDetect(@NonNull android.service.voice.AlwaysOnHotwordDetector.EventPayload, long, @NonNull android.service.voice.HotwordDetectionService.Callback);
@@ -10546,8 +10554,6 @@
method public void onDetect(@NonNull android.service.voice.HotwordDetectionService.Callback);
method public void onDetect(@NonNull android.os.ParcelFileDescriptor, @NonNull android.media.AudioFormat, @Nullable android.os.PersistableBundle, @NonNull android.service.voice.HotwordDetectionService.Callback);
method public void onUpdateState(@Nullable android.os.PersistableBundle, @Nullable android.os.SharedMemory, long, @Nullable java.util.function.IntConsumer);
- field public static final int INITIALIZATION_STATUS_CUSTOM_ERROR_1 = 1; // 0x1
- field public static final int INITIALIZATION_STATUS_CUSTOM_ERROR_2 = 2; // 0x2
field public static final int INITIALIZATION_STATUS_SUCCESS = 0; // 0x0
field public static final int INITIALIZATION_STATUS_UNKNOWN = 100; // 0x64
field public static final String SERVICE_INTERFACE = "android.service.voice.HotwordDetectionService";
@@ -12056,10 +12062,10 @@
field public static final int CALL_WAITING_STATUS_ENABLED = 1; // 0x1
field public static final int CALL_WAITING_STATUS_NOT_SUPPORTED = 4; // 0x4
field public static final int CALL_WAITING_STATUS_UNKNOWN_ERROR = 3; // 0x3
- field public static final String CAPABILITY_ALLOWED_NETWORK_TYPES_USED = "CAPABILITY_ALLOWED_NETWORK_TYPES_USED";
field public static final String CAPABILITY_NR_DUAL_CONNECTIVITY_CONFIGURATION_AVAILABLE = "CAPABILITY_NR_DUAL_CONNECTIVITY_CONFIGURATION_AVAILABLE";
field public static final String CAPABILITY_SECONDARY_LINK_BANDWIDTH_VISIBLE = "CAPABILITY_SECONDARY_LINK_BANDWIDTH_VISIBLE";
field public static final String CAPABILITY_THERMAL_MITIGATION_DATA_THROTTLING = "CAPABILITY_THERMAL_MITIGATION_DATA_THROTTLING";
+ field public static final String CAPABILITY_USES_ALLOWED_NETWORK_TYPES_BITMASK = "CAPABILITY_USES_ALLOWED_NETWORK_TYPES_BITMASK";
field public static final int CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES = -2; // 0xfffffffe
field public static final int CARRIER_PRIVILEGE_STATUS_HAS_ACCESS = 1; // 0x1
field public static final int CARRIER_PRIVILEGE_STATUS_NO_ACCESS = 0; // 0x0
@@ -14728,7 +14734,7 @@
method public String getDataDirectorySuffix();
method public String getErrorString(android.content.Context, int);
method public int getPackageId(android.content.res.Resources, String);
- method @NonNull public long[] getTimestamps();
+ method @NonNull public android.webkit.WebViewFactory.StartupTimestamps getStartupTimestamps();
method @Deprecated public void invokeDrawGlFunctor(android.view.View, long, boolean);
method public boolean isMultiProcessEnabled();
method public boolean isTraceTagEnabled();
@@ -14744,12 +14750,6 @@
method public static android.content.pm.PackageInfo getLoadedPackageInfo();
method public static int loadWebViewNativeLibraryFromPackage(String, ClassLoader);
method public static void prepareWebViewInZygote();
- field public static final int ADD_ASSETS_END = 4; // 0x4
- field public static final int ADD_ASSETS_START = 3; // 0x3
- field public static final int CREATE_CONTEXT_END = 2; // 0x2
- field public static final int CREATE_CONTEXT_START = 1; // 0x1
- field public static final int GET_CLASS_LOADER_END = 6; // 0x6
- field public static final int GET_CLASS_LOADER_START = 5; // 0x5
field public static final int LIBLOAD_ADDRESS_SPACE_NOT_RESERVED = 2; // 0x2
field public static final int LIBLOAD_FAILED_JNI_CALL = 7; // 0x7
field public static final int LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES = 4; // 0x4
@@ -14760,11 +14760,20 @@
field public static final int LIBLOAD_FAILED_WAITING_FOR_WEBVIEW_REASON_UNKNOWN = 8; // 0x8
field public static final int LIBLOAD_SUCCESS = 0; // 0x0
field public static final int LIBLOAD_WRONG_PACKAGE_NAME = 1; // 0x1
- field public static final int NATIVE_LOAD_END = 8; // 0x8
- field public static final int NATIVE_LOAD_START = 7; // 0x7
- field public static final int PROVIDER_CLASS_FOR_NAME_END = 10; // 0xa
- field public static final int PROVIDER_CLASS_FOR_NAME_START = 9; // 0x9
- field public static final int WEBVIEW_LOAD_START = 0; // 0x0
+ }
+
+ public static class WebViewFactory.StartupTimestamps {
+ method public long getAddAssetsEnd();
+ method public long getAddAssetsStart();
+ method public long getCreateContextEnd();
+ method public long getCreateContextStart();
+ method public long getGetClassLoaderEnd();
+ method public long getGetClassLoaderStart();
+ method public long getNativeLoadEnd();
+ method public long getNativeLoadStart();
+ method public long getProviderClassForNameEnd();
+ method public long getProviderClassForNameStart();
+ method public long getWebViewLoadStart();
}
public interface WebViewFactoryProvider {
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index c8e365e..12d9bee 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -2103,6 +2103,7 @@
public final class DeviceConfig {
field public static final String NAMESPACE_ALARM_MANAGER = "alarm_manager";
field public static final String NAMESPACE_ANDROID = "android";
+ field public static final String NAMESPACE_CONSTRAIN_DISPLAY_APIS = "constrain_display_apis";
field public static final String NAMESPACE_DEVICE_IDLE = "device_idle";
field public static final String NAMESPACE_JOB_SCHEDULER = "jobscheduler";
}
diff --git a/core/java/Android.bp b/core/java/Android.bp
index 793d0ef..6c001f3 100644
--- a/core/java/Android.bp
+++ b/core/java/Android.bp
@@ -169,6 +169,7 @@
filegroup {
name: "framework-jobscheduler-shared-srcs",
srcs: [
+ ":modules-utils-preconditions-srcs",
"com/android/internal/util/ArrayUtils.java",
"com/android/internal/util/BitUtils.java",
"com/android/internal/util/CollectionUtils.java",
@@ -178,7 +179,6 @@
"com/android/internal/util/FastXmlSerializer.java",
"com/android/internal/util/FunctionalUtils.java",
"com/android/internal/util/ParseUtils.java",
- "com/android/internal/util/Preconditions.java",
"com/android/internal/util/RingBufferIndices.java",
"com/android/internal/util/StatLogger.java",
"com/android/internal/util/XmlUtils.java",
@@ -189,9 +189,9 @@
filegroup {
name: "framework-permission-s-shared-srcs",
srcs: [
+ ":modules-utils-preconditions-srcs",
"com/android/internal/infra/AndroidFuture.java",
"com/android/internal/infra/ServiceConnector.java",
- "com/android/internal/util/Preconditions.java",
"com/android/internal/infra/AndroidFuture.aidl",
"com/android/internal/infra/IAndroidFuture.aidl",
"android/os/HandlerExecutor.java",
@@ -323,6 +323,7 @@
filegroup {
name: "framework-telephony-common-shared-srcs",
srcs: [
+ ":modules-utils-preconditions-srcs",
"android/os/RegistrantList.java",
"android/os/Registrant.java",
"android/util/IndentingPrintWriter.java",
@@ -336,7 +337,6 @@
"com/android/internal/util/HexDump.java",
"com/android/internal/util/IState.java",
"com/android/internal/util/IndentingPrintWriter.java",
- "com/android/internal/util/Preconditions.java",
"com/android/internal/util/State.java",
"com/android/internal/util/StateMachine.java",
"com/android/internal/util/UserIcons.java",
@@ -348,10 +348,10 @@
filegroup {
name: "framework-cellbroadcast-shared-srcs",
srcs: [
+ ":modules-utils-preconditions-srcs",
"android/os/HandlerExecutor.java",
"android/util/LocalLog.java",
"com/android/internal/util/IState.java",
- "com/android/internal/util/Preconditions.java",
"com/android/internal/util/State.java",
"com/android/internal/util/StateMachine.java",
],
@@ -360,10 +360,10 @@
filegroup {
name: "framework-ims-common-shared-srcs",
srcs: [
+ ":modules-utils-preconditions-srcs",
"android/os/RegistrantList.java",
"android/os/Registrant.java",
"com/android/internal/os/SomeArgs.java",
- "com/android/internal/util/Preconditions.java",
],
}
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index 01ea026..04c784e 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -373,7 +373,6 @@
* #FLAG_REQUEST_MULTI_FINGER_GESTURES} is disabled this flag has no effect.
*
* @see #FLAG_REQUEST_TOUCH_EXPLORATION_MODE
- * @hide
*/
public static final int FLAG_REQUEST_2_FINGER_PASSTHROUGH = 0x0002000;
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 295943d..854c9f2 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -970,8 +970,7 @@
private UiTranslationController mUiTranslationController;
private SplashScreen mSplashScreen;
- /** @hide */
- SplashScreenView mSplashScreenView;
+ private SplashScreenView mSplashScreenView;
private final WindowControllerCallback mWindowControllerCallback =
new WindowControllerCallback() {
@@ -1631,16 +1630,14 @@
}
}
- /**
- * Clear the splash screen view if exist.
- * @hide
- */
- public void detachSplashScreenView() {
- synchronized (this) {
- if (mSplashScreenView != null) {
- mSplashScreenView = null;
- }
- }
+ /** @hide */
+ public void setSplashScreenView(SplashScreenView v) {
+ mSplashScreenView = v;
+ }
+
+ /** @hide */
+ SplashScreenView getSplashScreenView() {
+ return mSplashScreenView;
}
/**
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 80f1e6e..306b54d 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -327,6 +327,9 @@
private static final String KEY_LAUNCHED_FROM_BUBBLE =
"android.activity.launchTypeBubble";
+ /** See {@link #setTransientLaunch()}. */
+ private static final String KEY_TRANSIENT_LAUNCH = "android.activity.transientLaunch";
+
/**
* @see #setLaunchCookie
* @hide
@@ -414,6 +417,7 @@
private int mSplashScreenThemeResId;
private boolean mRemoveWithTaskOrganizer;
private boolean mLaunchedFromBubble;
+ private boolean mTransientLaunch;
/**
* Create an ActivityOptions specifying a custom animation to run when
@@ -1166,6 +1170,7 @@
mSplashScreenThemeResId = opts.getInt(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);
}
/**
@@ -1663,6 +1668,28 @@
}
/**
+ * Sets whether the activity launch is part of a transient operation. If it is, it will not
+ * cause lifecycle changes in existing activities even if it were to occlude them (ie. other
+ * activities occluded by this one will not be paused or stopped until the launch is committed).
+ * As a consequence, it will start immediately since it doesn't need to wait for other
+ * lifecycles to evolve. Current user is recents.
+ * @hide
+ */
+ public ActivityOptions setTransientLaunch() {
+ mTransientLaunch = true;
+ return this;
+ }
+
+ /**
+ * @see #setTransientLaunch()
+ * @return whether the activity launch is part of a transient operation.
+ * @hide
+ */
+ public boolean getTransientLaunch() {
+ return mTransientLaunch;
+ }
+
+ /**
* Update the current values in this ActivityOptions from those supplied
* in <var>otherOptions</var>. Any values
* defined in <var>otherOptions</var> replace those in the base options.
@@ -1902,6 +1929,9 @@
if (mLaunchedFromBubble) {
b.putBoolean(KEY_LAUNCHED_FROM_BUBBLE, mLaunchedFromBubble);
}
+ if (mTransientLaunch) {
+ b.putBoolean(KEY_TRANSIENT_LAUNCH, mTransientLaunch);
+ }
return b;
}
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 3ebf545..92bdda3 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -36,6 +36,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.UserIdInt;
import android.app.assist.AssistContent;
import android.app.assist.AssistStructure;
import android.app.backup.BackupAgent;
@@ -61,6 +62,7 @@
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.Context;
+import android.content.Context.CreatePackageOptions;
import android.content.IContentProvider;
import android.content.IIntentReceiver;
import android.content.Intent;
@@ -72,6 +74,7 @@
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.PackageManager.ApplicationInfoFlags;
import android.content.pm.ParceledListSlice;
import android.content.pm.PermissionInfo;
import android.content.pm.ProviderInfo;
@@ -2367,16 +2370,22 @@
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
public final LoadedApk getPackageInfo(String packageName, CompatibilityInfo compatInfo,
- int flags) {
+ @CreatePackageOptions int flags) {
return getPackageInfo(packageName, compatInfo, flags, UserHandle.myUserId());
}
public final LoadedApk getPackageInfo(String packageName, CompatibilityInfo compatInfo,
- int flags, int userId) {
+ @CreatePackageOptions int flags, @UserIdInt int userId) {
+ return getPackageInfo(packageName, compatInfo, flags, userId, 0 /* packageFlags */);
+ }
+
+ public final LoadedApk getPackageInfo(String packageName, CompatibilityInfo compatInfo,
+ @CreatePackageOptions int flags, @UserIdInt int userId,
+ @ApplicationInfoFlags int packageFlags) {
final boolean differentUser = (UserHandle.myUserId() != userId);
ApplicationInfo ai = PackageManager.getApplicationInfoAsUserCached(
packageName,
- PackageManager.GET_SHARED_LIBRARY_FILES
+ packageFlags | PackageManager.GET_SHARED_LIBRARY_FILES
| PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
(userId < 0) ? UserHandle.myUserId() : userId);
synchronized (mResourcesManager) {
@@ -2419,7 +2428,7 @@
@UnsupportedAppUsage(trackingBug = 171933273)
public final LoadedApk getPackageInfo(ApplicationInfo ai, CompatibilityInfo compatInfo,
- int flags) {
+ @CreatePackageOptions int flags) {
boolean includeCode = (flags&Context.CONTEXT_INCLUDE_CODE) != 0;
boolean securityViolation = includeCode && ai.uid != 0
&& ai.uid != Process.SYSTEM_UID && (mBoundApplication != null
@@ -3509,7 +3518,8 @@
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
- r.intent.prepareToEnterProcess(isProtectedComponent(r.activityInfo));
+ r.intent.prepareToEnterProcess(isProtectedComponent(r.activityInfo),
+ appContext.getAttributionSource());
if (r.state != null) {
r.state.setClassLoader(cl);
}
@@ -3801,7 +3811,8 @@
for (int i=0; i<N; i++) {
ReferrerIntent intent = intents.get(i);
intent.setExtrasClassLoader(r.activity.getClassLoader());
- intent.prepareToEnterProcess(isProtectedComponent(r.activityInfo));
+ intent.prepareToEnterProcess(isProtectedComponent(r.activityInfo),
+ r.activity.getAttributionSource());
r.activity.mFragments.noteStateNotSaved();
mInstrumentation.callActivityOnNewIntent(r.activity, intent);
}
@@ -4049,10 +4060,7 @@
final SplashScreenView.Builder builder = new SplashScreenView.Builder(r.activity);
final SplashScreenView view = builder.createFromParcel(parcelable).build();
decorView.addView(view);
- view.cacheRootWindow(r.window);
- view.makeSystemUIColorsTransparent();
- r.activity.mSplashScreenView = view;
- view.attachHostActivity(r.activity);
+ view.attachHostActivityAndSetSystemUIColors(r.activity, r.window);
view.requestLayout();
// Ensure splash screen view is shown before remove the splash screen window.
final ViewRootImpl impl = decorView.getViewRootImpl();
@@ -4094,12 +4102,13 @@
@Override
public void handOverSplashScreenView(@NonNull ActivityClientRecord r) {
- if (r.activity.mSplashScreenView != null) {
- synchronized (this) {
- if (mSplashScreenGlobal != null) {
- mSplashScreenGlobal.dispatchOnExitAnimation(r.token,
- r.activity.mSplashScreenView);
- }
+ final SplashScreenView v = r.activity.getSplashScreenView();
+ if (v == null) {
+ return;
+ }
+ synchronized (this) {
+ if (mSplashScreenGlobal != null) {
+ mSplashScreenGlobal.dispatchOnExitAnimation(r.token, v);
}
}
}
@@ -4241,10 +4250,15 @@
if (data.info.splitName != null) {
context = (ContextImpl) context.createContextForSplit(data.info.splitName);
}
+ if (data.info.attributionTags != null && data.info.attributionTags.length > 0) {
+ final String attributionTag = data.info.attributionTags[0];
+ context = (ContextImpl) context.createAttributionContext(attributionTag);
+ }
java.lang.ClassLoader cl = context.getClassLoader();
data.intent.setExtrasClassLoader(cl);
data.intent.prepareToEnterProcess(
- isProtectedComponent(data.info) || isProtectedBroadcast(data.intent));
+ isProtectedComponent(data.info) || isProtectedBroadcast(data.intent),
+ context.getAttributionSource());
data.setExtrasClassLoader(cl);
receiver = packageInfo.getAppFactory()
.instantiateReceiver(cl, data.info.name, data.intent);
@@ -4435,6 +4449,10 @@
if (data.info.splitName != null) {
context = (ContextImpl) context.createContextForSplit(data.info.splitName);
}
+ if (data.info.attributionTags != null && data.info.attributionTags.length > 0) {
+ final String attributionTag = data.info.attributionTags[0];
+ context = (ContextImpl) context.createAttributionContext(attributionTag);
+ }
// Service resources must be initialized with the same loaders as the application
// context.
context.getResources().addLoaders(
@@ -4469,7 +4487,8 @@
if (s != null) {
try {
data.intent.setExtrasClassLoader(s.getClassLoader());
- data.intent.prepareToEnterProcess(isProtectedComponent(createData.info));
+ data.intent.prepareToEnterProcess(isProtectedComponent(createData.info),
+ s.getAttributionSource());
try {
if (!data.rebind) {
IBinder binder = s.onBind(data.intent);
@@ -4499,7 +4518,8 @@
if (s != null) {
try {
data.intent.setExtrasClassLoader(s.getClassLoader());
- data.intent.prepareToEnterProcess(isProtectedComponent(createData.info));
+ data.intent.prepareToEnterProcess(isProtectedComponent(createData.info),
+ s.getAttributionSource());
boolean doRebind = s.onUnbind(data.intent);
try {
if (doRebind) {
@@ -4588,7 +4608,8 @@
try {
if (data.args != null) {
data.args.setExtrasClassLoader(s.getClassLoader());
- data.args.prepareToEnterProcess(isProtectedComponent(createData.info));
+ data.args.prepareToEnterProcess(isProtectedComponent(createData.info),
+ s.getAttributionSource());
}
int res;
if (!data.taskRemoved) {
@@ -5241,7 +5262,8 @@
try {
if (ri.mData != null) {
ri.mData.setExtrasClassLoader(r.activity.getClassLoader());
- ri.mData.prepareToEnterProcess(isProtectedComponent(r.activityInfo));
+ ri.mData.prepareToEnterProcess(isProtectedComponent(r.activityInfo),
+ r.activity.getAttributionSource());
}
if (DEBUG_RESULTS) Slog.v(TAG,
"Delivering result to activity " + r + " : " + ri);
@@ -7342,6 +7364,10 @@
throw new RuntimeException(e);
}
}
+ if (info.attributionTags != null && info.attributionTags.length > 0) {
+ final String attributionTag = info.attributionTags[0];
+ c = c.createAttributionContext(attributionTag);
+ }
try {
final java.lang.ClassLoader cl = c.getClassLoader();
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 9ce37e4..daef8b1 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -26,6 +26,7 @@
import android.annotation.Nullable;
import android.annotation.UiContext;
import android.compat.annotation.UnsupportedAppUsage;
+import android.content.AttributionSource;
import android.content.AutofillOptions;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -47,6 +48,7 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.ApplicationInfoFlags;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.AssetManager;
import android.content.res.CompatResources;
@@ -60,7 +62,6 @@
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.net.Uri;
-import android.content.AttributionSource;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
@@ -1774,7 +1775,8 @@
intent.setExtrasClassLoader(getClassLoader());
// TODO: determine at registration time if caller is
// protecting themselves with signature permission
- intent.prepareToEnterProcess(ActivityThread.isProtectedBroadcast(intent));
+ intent.prepareToEnterProcess(ActivityThread.isProtectedBroadcast(intent),
+ getAttributionSource());
}
return intent;
} catch (RemoteException e) {
@@ -2492,6 +2494,13 @@
@Override
public Context createPackageContextAsUser(String packageName, int flags, UserHandle user)
throws NameNotFoundException {
+ return createPackageContextAsUser(packageName, flags, user, 0 /* packageFlags */);
+ }
+
+ @Override
+ public Context createPackageContextAsUser(
+ @NonNull String packageName, @CreatePackageOptions int flags, @NonNull UserHandle user,
+ @ApplicationInfoFlags int packageFlags) throws PackageManager.NameNotFoundException {
if (packageName.equals("system") || packageName.equals("android")) {
// The system resources are loaded in every application, so we can safely copy
// the context without reloading Resources.
@@ -2502,7 +2511,7 @@
}
LoadedApk pi = mMainThread.getPackageInfo(packageName, mResources.getCompatibilityInfo(),
- flags | CONTEXT_REGISTER_PACKAGE, user.getIdentifier());
+ flags | CONTEXT_REGISTER_PACKAGE, user.getIdentifier(), packageFlags);
if (pi != null) {
ContextImpl c = new ContextImpl(this, mMainThread, pi, mParams,
mAttributionSource.getAttributionTag(),
@@ -3035,8 +3044,16 @@
}
}
+ final String attributionTag;
+ if (activityInfo.attributionTags != null && activityInfo.attributionTags.length > 0) {
+ attributionTag = activityInfo.attributionTags[0];
+ } else {
+ attributionTag = null;
+ }
+
ContextImpl context = new ContextImpl(null, mainThread, packageInfo, ContextParams.EMPTY,
- null, null, activityInfo.splitName, activityToken, null, 0, classLoader, null);
+ attributionTag, null, activityInfo.splitName, activityToken, null, 0, classLoader,
+ null);
context.mContextType = CONTEXT_TYPE_ACTIVITY;
context.mIsConfigurationBasedContext = true;
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index ea6c874..4446fb7 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -1651,7 +1651,8 @@
intent.setExtrasClassLoader(cl);
// TODO: determine at registration time if caller is
// protecting themselves with signature permission
- intent.prepareToEnterProcess(ActivityThread.isProtectedBroadcast(intent));
+ intent.prepareToEnterProcess(ActivityThread.isProtectedBroadcast(intent),
+ mContext.getAttributionSource());
setExtrasClassLoader(cl);
receiver.setPendingResult(this);
receiver.onReceive(mContext, intent);
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index c6989ad..20305e9 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -5338,7 +5338,7 @@
}
final float extraMarginEndDpIfVisible = viewWidthDp + iconMarginDp;
result.setRightIconState(rightIcon != null /* visible */, viewWidthDp,
- extraMarginEndDpIfVisible, expanderSizeDp);
+ viewHeightDp, extraMarginEndDpIfVisible, expanderSizeDp);
}
/**
@@ -5375,6 +5375,8 @@
if (rightIcon != null) {
contentView.setViewLayoutWidth(R.id.right_icon,
result.mRightIconWidthDp, TypedValue.COMPLEX_UNIT_DIP);
+ contentView.setViewLayoutHeight(R.id.right_icon,
+ result.mRightIconHeightDp, TypedValue.COMPLEX_UNIT_DIP);
contentView.setViewVisibility(R.id.right_icon, View.VISIBLE);
contentView.setImageViewIcon(R.id.right_icon, rightIcon);
contentView.setIntTag(R.id.right_icon, R.id.tag_keep_when_showing_left_icon,
@@ -6476,10 +6478,11 @@
ApplicationInfo applicationInfo = n.extras.getParcelable(
EXTRA_BUILDER_APPLICATION_INFO);
Context builderContext;
- if (applicationInfo != null) {
+ if (applicationInfo != null && applicationInfo.packageName != null) {
try {
- builderContext = context.createApplicationContext(applicationInfo,
- Context.CONTEXT_RESTRICTED);
+ builderContext = context.createPackageContextAsUser(applicationInfo.packageName,
+ Context.CONTEXT_RESTRICTED,
+ UserHandle.getUserHandleForUid(applicationInfo.uid));
} catch (NameNotFoundException e) {
Log.e(TAG, "ApplicationInfo " + applicationInfo + " not found");
builderContext = context; // try with our context
@@ -12119,6 +12122,7 @@
private static class TemplateBindResult {
boolean mRightIconVisible;
float mRightIconWidthDp;
+ float mRightIconHeightDp;
/**
* The margin end that needs to be added to the heading so that it won't overlap
@@ -12143,10 +12147,11 @@
*/
public final MarginSet mTitleMarginSet = new MarginSet();
- public void setRightIconState(boolean visible, float widthDp,
+ public void setRightIconState(boolean visible, float widthDp, float heightDp,
float marginEndDpIfVisible, float expanderSizeDp) {
mRightIconVisible = visible;
mRightIconWidthDp = widthDp;
+ mRightIconHeightDp = heightDp;
mHeadingExtraMarginSet.setValues(0, marginEndDpIfVisible);
mHeadingFullMarginSet.setValues(expanderSizeDp, marginEndDpIfVisible + expanderSizeDp);
mTitleMarginSet.setValues(0, marginEndDpIfVisible + expanderSizeDp);
diff --git a/core/java/android/app/admin/DelegatedAdminReceiver.java b/core/java/android/app/admin/DelegatedAdminReceiver.java
index 36097c9..c74ddb2 100644
--- a/core/java/android/app/admin/DelegatedAdminReceiver.java
+++ b/core/java/android/app/admin/DelegatedAdminReceiver.java
@@ -104,6 +104,10 @@
* receiver's manifest in order to receive this callback. The default implementation
* simply throws {@link UnsupportedOperationException}.
*
+ * <p>
+ * This callback is triggered by a foreground broadcast and the app should ensure that any
+ * long-running work is not executed synchronously inside the callback.
+ *
* @param context The running context as per {@link #onReceive}.
* @param intent The received intent as per {@link #onReceive}.
* @param batchToken The token representing the current batch of network logs.
@@ -130,6 +134,10 @@
* the receiver's manifest in order to receive this callback. The default implementation
* simply throws {@link UnsupportedOperationException}.
*
+ * <p>
+ * This callback is triggered by a foreground broadcast and the app should ensure that any
+ * long-running work is not executed synchronously inside the callback.
+ *
* @param context The running context as per {@link #onReceive}.
* @param intent The received intent as per {@link #onReceive}.
* @see DevicePolicyManager#retrieveSecurityLogs
diff --git a/core/java/android/app/admin/DeviceAdminReceiver.java b/core/java/android/app/admin/DeviceAdminReceiver.java
index da64dcd..27e8c46 100644
--- a/core/java/android/app/admin/DeviceAdminReceiver.java
+++ b/core/java/android/app/admin/DeviceAdminReceiver.java
@@ -942,7 +942,12 @@
*
* <p>This callback will be re-triggered if the logs are not retrieved.
*
- * <p>This callback is only applicable to device owners.
+ * <p>This callback is only applicable to device owners and profile owners of
+ * organization-owned managed profiles.
+ *
+ * <p>
+ * This callback is triggered by a foreground broadcast and the app should ensure that any
+ * long-running work is not executed synchronously inside the callback.
*
* @param context The running context as per {@link #onReceive}.
* @param intent The received intent as per {@link #onReceive}.
@@ -961,7 +966,11 @@
* possible to retrieve the network logs batch with the most recent {@code batchToken} provided
* by this callback. See {@link DevicePolicyManager#setAffiliationIds}.
*
- * <p>This callback is only applicable to device owners.
+ * <p>This callback is only applicable to device owners and profile owners.
+ *
+ * <p>
+ * This callback is triggered by a foreground broadcast and the app should ensure that any
+ * long-running work is not executed synchronously inside the callback.
*
* @param context The running context as per {@link #onReceive}.
* @param intent The received intent as per {@link #onReceive}.
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 38b19ae..c23cacb 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -10369,11 +10369,11 @@
/**
* Called by device owners to set the user's global location setting.
*
- * <p><b>Note: </b> this call is ignored on
- * {@link android.content.pm.PackageManager#FEATURE_AUTOMOTIVE automotive builds}.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with
- * @param locationEnabled whether location should be enabled or disabled
+ * @param locationEnabled whether location should be enabled or disabled. <b>Note: </b> on
+ * {@link android.content.pm.PackageManager#FEATURE_AUTOMOTIVE automotive builds}, calls to
+ * disable will be ignored.
* @throws SecurityException if {@code admin} is not a device owner.
*/
public void setLocationEnabled(@NonNull ComponentName admin, boolean locationEnabled) {
diff --git a/core/java/android/app/timezonedetector/TimeZoneDetector.java b/core/java/android/app/timezonedetector/TimeZoneDetector.java
index b216e91..a71cffe 100644
--- a/core/java/android/app/timezonedetector/TimeZoneDetector.java
+++ b/core/java/android/app/timezonedetector/TimeZoneDetector.java
@@ -48,6 +48,13 @@
String SHELL_COMMAND_SET_AUTO_DETECTION_ENABLED = "set_auto_detection_enabled";
/**
+ * A shell command that prints whether the telephony-based time zone detection feature is
+ * supported on the device.
+ * @hide
+ */
+ String SHELL_COMMAND_IS_TELEPHONY_DETECTION_SUPPORTED = "is_telephony_detection_supported";
+
+ /**
* A shell command that prints whether the geolocation-based time zone detection feature is
* supported on the device.
* @hide
diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java
index 9f1132b..fe99f85 100644
--- a/core/java/android/app/usage/NetworkStatsManager.java
+++ b/core/java/android/app/usage/NetworkStatsManager.java
@@ -644,7 +644,10 @@
: NetworkTemplate.buildTemplateMobileAll(subscriberId);
break;
case ConnectivityManager.TYPE_WIFI:
- template = NetworkTemplate.buildTemplateWifiWildcard();
+ template = subscriberId == null
+ ? NetworkTemplate.buildTemplateWifiWildcard()
+ : NetworkTemplate.buildTemplateWifi(NetworkTemplate.WIFI_NETWORKID_ALL,
+ subscriberId);
break;
default:
throw new IllegalArgumentException("Cannot create template for network type "
@@ -655,14 +658,14 @@
}
/**
- * Notify {@code NetworkStatsService} about network status changed.
+ * Notify {@code NetworkStatsService} about network status changed.
*
- * Notifies NetworkStatsService of network state changes for data usage accounting purposes.
+ * Notifies NetworkStatsService of network state changes for data usage accounting purposes.
*
- * To avoid races that attribute data usage to wrong network, such as new network with
- * the same interface after SIM hot-swap, this function will not return until
- * {@code NetworkStatsService} finishes its work of retrieving traffic statistics from
- * all data sources.
+ * To avoid races that attribute data usage to wrong network, such as new network with
+ * the same interface after SIM hot-swap, this function will not return until
+ * {@code NetworkStatsService} finishes its work of retrieving traffic statistics from
+ * all data sources.
*
* @param defaultNetworks the list of all networks that could be used by network traffic that
* does not explicitly select a network.
@@ -689,8 +692,7 @@
Objects.requireNonNull(defaultNetworks);
Objects.requireNonNull(networkStateSnapshots);
Objects.requireNonNull(underlyingNetworkInfos);
- // TODO: Change internal namings after the name is decided.
- mService.forceUpdateIfaces(defaultNetworks.toArray(new Network[0]),
+ mService.notifyNetworkStatus(defaultNetworks.toArray(new Network[0]),
networkStateSnapshots.toArray(new NetworkStateSnapshot[0]), activeIface,
underlyingNetworkInfos.toArray(new UnderlyingNetworkInfo[0]));
} catch (RemoteException e) {
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index 2ed44ec..3b11a19 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -37,6 +37,7 @@
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.Parcelable;
+import android.os.UserHandle;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Pair;
@@ -718,9 +719,10 @@
protected Context getRemoteContext() {
try {
// Return if cloned successfully, otherwise default
- Context newContext = mContext.createApplicationContext(
- mInfo.providerInfo.applicationInfo,
- Context.CONTEXT_RESTRICTED);
+ final ApplicationInfo info = mInfo.providerInfo.applicationInfo;
+ Context newContext = mContext.createPackageContextAsUser(info.packageName,
+ Context.CONTEXT_RESTRICTED,
+ UserHandle.getUserHandleForUid(info.uid));
if (mColorResources != null) {
mColorResources.apply(newContext);
}
@@ -909,7 +911,8 @@
return false;
}
for (int i = 0; i < oldColors.size(); i++) {
- if (oldColors.valueAt(i) != newColors.get(oldColors.keyAt(i))) {
+ if (oldColors.keyAt(i) != newColors.keyAt(i)
+ || oldColors.valueAt(i) != newColors.valueAt(i)) {
return false;
}
}
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 9fc1f88..5494172 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -3258,39 +3258,14 @@
/** @hide */
@Retention(RetentionPolicy.SOURCE)
- @IntDef(prefix = { "OOB_ERROR_" }, value = {
- OOB_ERROR_UNKNOWN,
- OOB_ERROR_ANOTHER_ACTIVE_REQUEST,
- OOB_ERROR_ADAPTER_DISABLED
+ @IntDef(value = {
+ BluetoothStatusCodes.ERROR_UNKNOWN,
+ BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED,
+ BluetoothStatusCodes.ERROR_ANOTHER_ACTIVE_OOB_REQUEST,
})
public @interface OobError {}
/**
- * An unknown error has occurred in the controller, stack, or callback pipeline.
- *
- * @hide
- */
- @SystemApi
- public static final int OOB_ERROR_UNKNOWN = 0;
-
- /**
- * If another application has already requested {@link OobData} then another fetch will be
- * disallowed until the callback is removed.
- *
- * @hide
- */
- @SystemApi
- public static final int OOB_ERROR_ANOTHER_ACTIVE_REQUEST = 1;
-
- /**
- * The adapter is currently disabled, please enable it.
- *
- * @hide
- */
- @SystemApi
- public static final int OOB_ERROR_ADAPTER_DISABLED = 2;
-
- /**
* Provides callback methods for receiving {@link OobData} from the host stack, as well as an
* error interface in order to allow the caller to determine next steps based on the {@code
* ErrorCode}.
@@ -3310,7 +3285,7 @@
/**
* Provides feedback when things don't go as expected.
*
- * @param errorCode - the code descibing the type of error that occurred.
+ * @param errorCode - the code describing the type of error that occurred.
*/
void onError(@OobError int errorCode);
}
@@ -3407,7 +3382,7 @@
Preconditions.checkNotNull(callback);
if (!isEnabled()) {
Log.w(TAG, "generateLocalOobData(): Adapter isn't enabled!");
- callback.onError(OOB_ERROR_ADAPTER_DISABLED);
+ callback.onError(BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED);
} else {
try {
mService.generateLocalOobData(transport, new WrappedOobDataCallback(callback,
@@ -4210,141 +4185,45 @@
*/
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = { "REASON_" }, value = {
- REASON_UNKNOWN,
- REASON_LOCAL_REQUEST,
- REASON_REMOTE_REQUEST,
- REASON_LOCAL_ERROR,
- REASON_REMOTE_ERROR,
- REASON_TIMEOUT,
- REASON_SECURITY,
- REASON_SYSTEM_POLICY,
- REASON_RESOURCE_LIMIT_REACHED,
- REASON_CONNECTION_EXISTS,
- REASON_BAD_PARAMETERS})
+ BluetoothStatusCodes.ERROR_UNKNOWN,
+ BluetoothStatusCodes.ERROR_DISCONNECT_REASON_LOCAL_REQUEST,
+ BluetoothStatusCodes.ERROR_DISCONNECT_REASON_REMOTE_REQUEST,
+ BluetoothStatusCodes.ERROR_DISCONNECT_REASON_LOCAL,
+ BluetoothStatusCodes.ERROR_DISCONNECT_REASON_REMOTE,
+ BluetoothStatusCodes.ERROR_DISCONNECT_REASON_TIMEOUT,
+ BluetoothStatusCodes.ERROR_DISCONNECT_REASON_SECURITY,
+ BluetoothStatusCodes.ERROR_DISCONNECT_REASON_SYSTEM_POLICY,
+ BluetoothStatusCodes.ERROR_DISCONNECT_REASON_RESOURCE_LIMIT_REACHED,
+ BluetoothStatusCodes.ERROR_DISCONNECT_REASON_CONNECTION_ALREADY_EXISTS,
+ BluetoothStatusCodes.ERROR_DISCONNECT_REASON_BAD_PARAMETERS})
public @interface DisconnectReason {}
/**
- * Indicates that the ACL disconnected due to an unknown reason.
- */
- public static final int REASON_UNKNOWN = 0;
-
- /**
- * Indicates that the ACL disconnected due to an explicit request from the local device.
- * <p>
- * Example cause: This is a normal disconnect reason, e.g., user/app initiates
- * disconnection.
- */
- public static final int REASON_LOCAL_REQUEST = 1;
-
- /**
- * Indicates that the ACL disconnected due to an explicit request from the remote device.
- * <p>
- * Example cause: This is a normal disconnect reason, e.g., user/app initiates
- * disconnection.
- * <p>
- * Example solution: The app can also prompt the user to check their remote device.
- */
- public static final int REASON_REMOTE_REQUEST = 2;
-
- /**
- * Generic disconnect reason indicating the ACL disconnected due to an error on the local
- * device.
- * <p>
- * Example solution: Prompt the user to check their local device (e.g., phone, car
- * headunit).
- */
- public static final int REASON_LOCAL_ERROR = 3;
-
- /**
- * Generic disconnect reason indicating the ACL disconnected due to an error on the remote
- * device.
- * <p>
- * Example solution: Prompt the user to check their remote device (e.g., headset, car
- * headunit, watch).
- */
- public static final int REASON_REMOTE_ERROR = 4;
-
- /**
- * Indicates that the ACL disconnected due to a timeout.
- * <p>
- * Example cause: remote device might be out of range.
- * <p>
- * Example solution: Prompt user to verify their remote device is on or in
- * connection/pairing mode.
- */
- public static final int REASON_TIMEOUT = 5;
-
- /**
- * Indicates that the ACL disconnected due to link key issues.
- * <p>
- * Example cause: Devices are either unpaired or remote device is refusing our pairing
- * request.
- * <p>
- * Example solution: Prompt user to unpair and pair again.
- */
- public static final int REASON_SECURITY = 6;
-
- /**
- * Indicates that the ACL disconnected due to the local device's system policy.
- * <p>
- * Example cause: privacy policy, power management policy, permissions, etc.
- * <p>
- * Example solution: Prompt the user to check settings, or check with their system
- * administrator (e.g. some corp-managed devices do not allow OPP connection).
- */
- public static final int REASON_SYSTEM_POLICY = 7;
-
- /**
- * Indicates that the ACL disconnected due to resource constraints, either on the local
- * device or the remote device.
- * <p>
- * Example cause: controller is busy, memory limit reached, maximum number of connections
- * reached.
- * <p>
- * Example solution: The app should wait and try again. If still failing, prompt the user
- * to disconnect some devices, or toggle Bluetooth on the local and/or the remote device.
- */
- public static final int REASON_RESOURCE_LIMIT_REACHED = 8;
-
- /**
- * Indicates that the ACL disconnected because another ACL connection already exists.
- */
- public static final int REASON_CONNECTION_EXISTS = 9;
-
- /**
- * Indicates that the ACL disconnected due to incorrect parameters passed in from the app.
- * <p>
- * Example solution: Change parameters and try again. If error persists, the app can report
- * telemetry and/or log the error in a bugreport.
- */
- public static final int REASON_BAD_PARAMETERS = 10;
-
- /**
* Returns human-readable strings corresponding to {@link DisconnectReason}.
*/
public static String disconnectReasonText(@DisconnectReason int reason) {
switch (reason) {
- case REASON_UNKNOWN:
+ case BluetoothStatusCodes.ERROR_UNKNOWN:
return "Reason unknown";
- case REASON_LOCAL_REQUEST:
+ case BluetoothStatusCodes.ERROR_DISCONNECT_REASON_LOCAL_REQUEST:
return "Local request";
- case REASON_REMOTE_REQUEST:
+ case BluetoothStatusCodes.ERROR_DISCONNECT_REASON_REMOTE_REQUEST:
return "Remote request";
- case REASON_LOCAL_ERROR:
+ case BluetoothStatusCodes.ERROR_DISCONNECT_REASON_LOCAL:
return "Local error";
- case REASON_REMOTE_ERROR:
+ case BluetoothStatusCodes.ERROR_DISCONNECT_REASON_REMOTE:
return "Remote error";
- case REASON_TIMEOUT:
+ case BluetoothStatusCodes.ERROR_DISCONNECT_REASON_TIMEOUT:
return "Timeout";
- case REASON_SECURITY:
+ case BluetoothStatusCodes.ERROR_DISCONNECT_REASON_SECURITY:
return "Security";
- case REASON_SYSTEM_POLICY:
+ case BluetoothStatusCodes.ERROR_DISCONNECT_REASON_SYSTEM_POLICY:
return "System policy";
- case REASON_RESOURCE_LIMIT_REACHED:
+ case BluetoothStatusCodes.ERROR_DISCONNECT_REASON_RESOURCE_LIMIT_REACHED:
return "Resource constrained";
- case REASON_CONNECTION_EXISTS:
+ case BluetoothStatusCodes.ERROR_DISCONNECT_REASON_CONNECTION_ALREADY_EXISTS:
return "Connection already exists";
- case REASON_BAD_PARAMETERS:
+ case BluetoothStatusCodes.ERROR_DISCONNECT_REASON_BAD_PARAMETERS:
return "Bad parameters";
default:
return "Unrecognized disconnect reason: " + reason;
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index 4032663..f2496fe 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -1190,6 +1190,11 @@
return devices;
}
+ /** {@hide} */
+ public void prepareToEnterProcess(AttributionSource attributionSource) {
+ setAttributionSource(attributionSource);
+ }
+
@Override
public boolean equals(@Nullable Object o) {
if (o instanceof BluetoothDevice) {
@@ -1346,6 +1351,17 @@
return null;
}
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = {
+ BluetoothStatusCodes.SUCCESS,
+ BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED,
+ BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED,
+ BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION,
+ BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED
+ })
+ public @interface SetAliasReturnValues{}
+
/**
* Sets the locally modifiable name (alias) of the remote Bluetooth device. This method
* overwrites the previously stored alias. The new alias is saved in local
@@ -1353,34 +1369,35 @@
*
* <p>This method requires the calling app to be associated with Companion Device Manager (see
* {@link android.companion.CompanionDeviceManager#associate(AssociationRequest,
- * android.companion.CompanionDeviceManager.Callback, Handler)}) and have the {@link
- * android.Manifest.permission#BLUETOOTH} permission. Alternatively, if the caller has the
- * {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED} permission, they can bypass the
- * Companion Device Manager association requirement.
+ * android.companion.CompanionDeviceManager.Callback, Handler)}) and have the
+ * {@link android.Manifest.permission#BLUETOOTH_CONNECT} permission. Alternatively, if the
+ * caller has the {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED} permission, they can
+ * bypass the Companion Device Manager association requirement as well as other permission
+ * requirements.
*
- * @param alias is the new locally modifiable name for the remote Bluetooth device which must be
- * non-null and not the empty string.
- * @return {@code true} if the alias is successfully set, {@code false} on error
- * @throws IllegalArgumentException if the alias is {@code null} or the empty string
+ * @param alias is the new locally modifiable name for the remote Bluetooth device which must
+ * be the empty string. If null, we clear the alias.
+ * @return whether the alias was successfully changed
+ * @throws IllegalArgumentException if the alias is the empty string
*/
@RequiresLegacyBluetoothPermission
@RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean setAlias(@NonNull String alias) {
- if (alias == null || alias.isEmpty()) {
- throw new IllegalArgumentException("Cannot set the alias to null or the empty string");
+ public @SetAliasReturnValues int setAlias(@Nullable String alias) {
+ if (alias != null && alias.isEmpty()) {
+ throw new IllegalArgumentException("alias cannot be the empty string");
}
final IBluetooth service = sService;
if (service == null) {
Log.e(TAG, "BT not enabled. Cannot set Remote Device name");
- return false;
+ return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
}
try {
return service.setRemoteAlias(this, alias, mAttributionSource);
} catch (RemoteException e) {
Log.e(TAG, "", e);
+ throw e.rethrowFromSystemServer();
}
- return false;
}
/**
diff --git a/core/java/android/bluetooth/BluetoothStatusCodes.java b/core/java/android/bluetooth/BluetoothStatusCodes.java
new file mode 100644
index 0000000..31bb0f6
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothStatusCodes.java
@@ -0,0 +1,205 @@
+/*
+ * 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.bluetooth;
+
+import android.annotation.SystemApi;
+
+/**
+ * A class with constants representing possible return values for Bluetooth APIs. General return
+ * values occupy the range 0 to 99. Profile-specific return values occupy the range 100-999.
+ * API-specific return values start at 1000. The exception to this is the "other" error code which
+ * occupies the max integer value.
+ */
+public final class BluetoothStatusCodes {
+
+ private BluetoothStatusCodes() {}
+
+ /**
+ * Indicates that the API call was successful
+ */
+ public static final int SUCCESS = 0;
+
+ /**
+ * Error code indicating that Bluetooth is not enabled
+ */
+ public static final int ERROR_BLUETOOTH_NOT_ENABLED = 1;
+
+ /**
+ * Error code indicating that the API call was initiated by neither the system nor the active
+ * Zuser
+ */
+ public static final int ERROR_BLUETOOTH_NOT_ALLOWED = 2;
+
+ /**
+ * Error code indicating that the Bluetooth Device specified is not bonded
+ */
+ public static final int ERROR_DEVICE_NOT_BONDED = 3;
+
+ /**
+ * Error code indicating that the Bluetooth Device specified is not connected, but is bonded
+ *
+ * @hide
+ */
+ public static final int ERROR_DEVICE_NOT_CONNECTED = 4;
+
+ /**
+ * Error code indicating that the caller does not have the
+ * {@link android.Manifest.permission#BLUETOOTH_ADVERTISE} permission
+ *
+ * @hide
+ */
+ public static final int ERROR_MISSING_BLUETOOTH_ADVERTISE_PERMISSION = 5;
+
+ /**
+ * Error code indicating that the caller does not have the
+ * {@link android.Manifest.permission#BLUETOOTH_CONNECT} permission
+ */
+ public static final int ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION = 6;
+
+ /**
+ * Error code indicating that the caller does not have the
+ * {@link android.Manifest.permission#BLUETOOTH_SCAN} permission
+ *
+ * @hide
+ */
+ public static final int ERROR_MISSING_BLUETOOTH_SCAN_PERMISSION = 7;
+
+ /**
+ * If another application has already requested {@link OobData} then another fetch will be
+ * disallowed until the callback is removed.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int ERROR_ANOTHER_ACTIVE_OOB_REQUEST = 1000;
+
+ /**
+ * Indicates that the ACL disconnected due to an explicit request from the local device.
+ * <p>
+ * Example cause: This is a normal disconnect reason, e.g., user/app initiates
+ * disconnection.
+ *
+ * @hide
+ */
+ public static final int ERROR_DISCONNECT_REASON_LOCAL_REQUEST = 1100;
+
+ /**
+ * Indicates that the ACL disconnected due to an explicit request from the remote device.
+ * <p>
+ * Example cause: This is a normal disconnect reason, e.g., user/app initiates
+ * disconnection.
+ * <p>
+ * Example solution: The app can also prompt the user to check their remote device.
+ *
+ * @hide
+ */
+ public static final int ERROR_DISCONNECT_REASON_REMOTE_REQUEST = 1101;
+
+ /**
+ * Generic disconnect reason indicating the ACL disconnected due to an error on the local
+ * device.
+ * <p>
+ * Example solution: Prompt the user to check their local device (e.g., phone, car
+ * headunit).
+ *
+ * @hide
+ */
+ public static final int ERROR_DISCONNECT_REASON_LOCAL = 1102;
+
+ /**
+ * Generic disconnect reason indicating the ACL disconnected due to an error on the remote
+ * device.
+ * <p>
+ * Example solution: Prompt the user to check their remote device (e.g., headset, car
+ * headunit, watch).
+ *
+ * @hide
+ */
+ public static final int ERROR_DISCONNECT_REASON_REMOTE = 1103;
+
+ /**
+ * Indicates that the ACL disconnected due to a timeout.
+ * <p>
+ * Example cause: remote device might be out of range.
+ * <p>
+ * Example solution: Prompt user to verify their remote device is on or in
+ * connection/pairing mode.
+ *
+ * @hide
+ */
+ public static final int ERROR_DISCONNECT_REASON_TIMEOUT = 1104;
+
+ /**
+ * Indicates that the ACL disconnected due to link key issues.
+ * <p>
+ * Example cause: Devices are either unpaired or remote device is refusing our pairing
+ * request.
+ * <p>
+ * Example solution: Prompt user to unpair and pair again.
+ *
+ * @hide
+ */
+ public static final int ERROR_DISCONNECT_REASON_SECURITY = 1105;
+
+ /**
+ * Indicates that the ACL disconnected due to the local device's system policy.
+ * <p>
+ * Example cause: privacy policy, power management policy, permissions, etc.
+ * <p>
+ * Example solution: Prompt the user to check settings, or check with their system
+ * administrator (e.g. some corp-managed devices do not allow OPP connection).
+ *
+ * @hide
+ */
+ public static final int ERROR_DISCONNECT_REASON_SYSTEM_POLICY = 1106;
+
+ /**
+ * Indicates that the ACL disconnected due to resource constraints, either on the local
+ * device or the remote device.
+ * <p>
+ * Example cause: controller is busy, memory limit reached, maximum number of connections
+ * reached.
+ * <p>
+ * Example solution: The app should wait and try again. If still failing, prompt the user
+ * to disconnect some devices, or toggle Bluetooth on the local and/or the remote device.
+ *
+ * @hide
+ */
+ public static final int ERROR_DISCONNECT_REASON_RESOURCE_LIMIT_REACHED = 1107;
+
+ /**
+ * Indicates that the ACL disconnected because another ACL connection already exists.
+ *
+ * @hide
+ */
+ public static final int ERROR_DISCONNECT_REASON_CONNECTION_ALREADY_EXISTS = 1108;
+
+ /**
+ * Indicates that the ACL disconnected due to incorrect parameters passed in from the app.
+ * <p>
+ * Example solution: Change parameters and try again. If error persists, the app can report
+ * telemetry and/or log the error in a bugreport.
+ *
+ * @hide
+ */
+ public static final int ERROR_DISCONNECT_REASON_BAD_PARAMETERS = 1109;
+
+ /**
+ * Indicates that an unknown error has occurred has occurred.
+ */
+ public static final int ERROR_UNKNOWN = Integer.MAX_VALUE;
+}
diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java
index 0e25d8a..e6ffded 100644
--- a/core/java/android/companion/CompanionDeviceManager.java
+++ b/core/java/android/companion/CompanionDeviceManager.java
@@ -338,21 +338,24 @@
*
* @param packageName the package name of the calling app
* @param deviceMacAddress the bluetooth device's mac address
- * @param userId the calling user's identifier
+ * @param user the user handle that currently hosts the package being queried for a companion
+ * device association
* @return true if it was recently associated and we can bypass the dialog, false otherwise
* @hide
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.MANAGE_COMPANION_DEVICES)
public boolean canPairWithoutPrompt(@NonNull String packageName,
- @NonNull String deviceMacAddress, int userId) {
+ @NonNull String deviceMacAddress, @NonNull UserHandle user) {
if (!checkFeaturePresent()) {
return false;
}
Objects.requireNonNull(packageName, "package name cannot be null");
Objects.requireNonNull(deviceMacAddress, "device mac address cannot be null");
+ Objects.requireNonNull(user, "user handle cannot be null");
try {
- return mService.canPairWithoutPrompt(packageName, deviceMacAddress, userId);
+ return mService.canPairWithoutPrompt(packageName, deviceMacAddress,
+ user.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/content/ClipData.java b/core/java/android/content/ClipData.java
index 6ab1975..54b39bd 100644
--- a/core/java/android/content/ClipData.java
+++ b/core/java/android/content/ClipData.java
@@ -1034,14 +1034,14 @@
}
/** {@hide} */
- public void prepareToEnterProcess() {
+ public void prepareToEnterProcess(AttributionSource source) {
final int size = mItems.size();
for (int i = 0; i < size; i++) {
final Item item = mItems.get(i);
if (item.mIntent != null) {
// We can't recursively claim that this data is from a protected
// component, since it may have been filled in by a malicious app
- item.mIntent.prepareToEnterProcess(false);
+ item.mIntent.prepareToEnterProcess(false, source);
}
}
}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 6a22491..fc676cf 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -46,6 +46,7 @@
import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.ApplicationInfoFlags;
import android.content.res.AssetManager;
import android.content.res.ColorStateList;
import android.content.res.Configuration;
@@ -6230,6 +6231,23 @@
}
/**
+ * Similar to {@link #createPackageContextAsUser(String, int, UserHandle)}, but also allows
+ * specifying the flags used to retrieve the {@link ApplicationInfo} of the package.
+ *
+ * @hide
+ */
+ @NonNull
+ public Context createPackageContextAsUser(
+ @NonNull String packageName, @CreatePackageOptions int flags, @NonNull UserHandle user,
+ @ApplicationInfoFlags int packageFlags)
+ throws PackageManager.NameNotFoundException {
+ if (Build.IS_ENG) {
+ throw new IllegalStateException("createPackageContextAsUser not overridden!");
+ }
+ return this;
+ }
+
+ /**
* Similar to {@link #createPackageContext(String, int)}, but for the own package with a
* different {@link UserHandle}. For example, {@link #getContentResolver()}
* will open any {@link Uri} as the given user.
@@ -6248,10 +6266,18 @@
/**
* Creates a context given an {@link android.content.pm.ApplicationInfo}.
*
+ * @deprecated use {@link #createPackageContextAsUser(String, int, UserHandle, int)}
+ * If an application caches an ApplicationInfo and uses it to call this method,
+ * the app will not get the most recent version of Runtime Resource Overlays for
+ * that application. To make things worse, the LoadedApk stored in
+ * {@code ActivityThread#mResourcePackages} is updated using the old ApplicationInfo
+ * causing further uses of the cached LoadedApk to return outdated information.
+ *
* @hide
*/
@SuppressWarnings("HiddenAbstractMethod")
@UnsupportedAppUsage
+ @Deprecated
public abstract Context createApplicationContext(ApplicationInfo application,
@CreatePackageOptions int flags) throws PackageManager.NameNotFoundException;
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 6324d0e..cf0dc8c 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -1009,6 +1009,14 @@
/** @hide */
@Override
+ public Context createPackageContextAsUser(String packageName, int flags, UserHandle user,
+ int packageFlags)
+ throws PackageManager.NameNotFoundException {
+ return mBase.createPackageContextAsUser(packageName, flags, user, packageFlags);
+ }
+
+ /** @hide */
+ @Override
public Context createContextAsUser(UserHandle user, @CreatePackageOptions int flags) {
return mBase.createContextAsUser(user, flags);
}
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index bbb49fb..a436fa4 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -31,6 +31,7 @@
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.app.AppGlobals;
+import android.bluetooth.BluetoothDevice;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
@@ -11439,7 +11440,7 @@
/**
* @hide
*/
- public void prepareToEnterProcess(boolean fromProtectedComponent) {
+ public void prepareToEnterProcess(boolean fromProtectedComponent, AttributionSource source) {
// We just entered destination process, so we should be able to read all
// parcelables inside.
setDefusable(true);
@@ -11447,10 +11448,10 @@
if (mSelector != null) {
// We can't recursively claim that this data is from a protected
// component, since it may have been filled in by a malicious app
- mSelector.prepareToEnterProcess(false);
+ mSelector.prepareToEnterProcess(false, source);
}
if (mClipData != null) {
- mClipData.prepareToEnterProcess();
+ mClipData.prepareToEnterProcess(source);
}
if (mContentUserHint != UserHandle.USER_CURRENT) {
@@ -11463,6 +11464,16 @@
if (fromProtectedComponent) {
mLocalFlags |= LOCAL_FLAG_FROM_PROTECTED_COMPONENT;
}
+
+ // Special attribution fix-up logic for any BluetoothDevice extras
+ // passed via Bluetooth intents
+ if (mAction != null && mAction.startsWith("android.bluetooth.")
+ && hasExtra(BluetoothDevice.EXTRA_DEVICE)) {
+ final BluetoothDevice device = getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
+ if (device != null) {
+ device.prepareToEnterProcess(source);
+ }
+ }
}
/** @hide */
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index fbed907..03f6380 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -17,8 +17,8 @@
package android.content.pm;
import android.annotation.IntDef;
-import android.annotation.SuppressLint;
import android.annotation.TestApi;
+import android.app.Activity;
import android.app.compat.CompatChanges;
import android.compat.annotation.ChangeId;
import android.compat.annotation.Disabled;
@@ -1174,13 +1174,6 @@
*/
public WindowLayout windowLayout;
- /**
- * Attribution tags for finer grained calls if a {@link
- * android.content.Context#sendBroadcast(Intent, String)} is used with a permission.
- */
- @SuppressLint("MissingNullability")
- public String[] attributionTags;
-
public ActivityInfo() {
}
@@ -1209,7 +1202,6 @@
mMaxAspectRatio = orig.mMaxAspectRatio;
mMinAspectRatio = orig.mMinAspectRatio;
supportsSizeChanges = orig.supportsSizeChanges;
- attributionTags = orig.attributionTags;
}
/**
@@ -1532,15 +1524,6 @@
if (supportsSizeChanges) {
pw.println(prefix + "supportsSizeChanges=true");
}
- if (attributionTags != null && attributionTags.length > 0) {
- StringBuilder tags = new StringBuilder();
- tags.append(attributionTags[0]);
- for (int i = 1; i < attributionTags.length; i++) {
- tags.append(", ");
- tags.append(attributionTags[i]);
- }
- pw.println(prefix + "attributionTags=[" + tags + "]");
- }
super.dumpBack(pw, prefix, dumpFlags);
}
@@ -1586,7 +1569,6 @@
dest.writeFloat(mMaxAspectRatio);
dest.writeFloat(mMinAspectRatio);
dest.writeBoolean(supportsSizeChanges);
- dest.writeString8Array(attributionTags);
}
/**
@@ -1706,7 +1688,6 @@
mMaxAspectRatio = source.readFloat();
mMinAspectRatio = source.readFloat();
supportsSizeChanges = source.readBoolean();
- attributionTags = source.createString8Array();
}
/**
diff --git a/core/java/android/content/pm/AppSearchShortcutInfo.java b/core/java/android/content/pm/AppSearchShortcutInfo.java
index afaecec..63f93bf 100644
--- a/core/java/android/content/pm/AppSearchShortcutInfo.java
+++ b/core/java/android/content/pm/AppSearchShortcutInfo.java
@@ -92,7 +92,7 @@
.setIndexingType(AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_PREFIXES)
.build()
- ).addProperty(new AppSearchSchema.Int64PropertyConfig.Builder(KEY_SHORT_LABEL_RES_ID)
+ ).addProperty(new AppSearchSchema.LongPropertyConfig.Builder(KEY_SHORT_LABEL_RES_ID)
.setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
.build()
@@ -108,7 +108,7 @@
.setIndexingType(AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_PREFIXES)
.build()
- ).addProperty(new AppSearchSchema.Int64PropertyConfig.Builder(KEY_LONG_LABEL_RES_ID)
+ ).addProperty(new AppSearchSchema.LongPropertyConfig.Builder(KEY_LONG_LABEL_RES_ID)
.setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
.build()
@@ -124,7 +124,7 @@
.setIndexingType(AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_NONE)
.build()
- ).addProperty(new AppSearchSchema.Int64PropertyConfig.Builder(
+ ).addProperty(new AppSearchSchema.LongPropertyConfig.Builder(
KEY_DISABLED_MESSAGE_RES_ID)
.setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
.build()
@@ -170,7 +170,7 @@
.setIndexingType(AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_EXACT_TERMS)
.build()
- ).addProperty(new AppSearchSchema.Int64PropertyConfig.Builder(KEY_IMPLICIT_RANK)
+ ).addProperty(new AppSearchSchema.LongPropertyConfig.Builder(KEY_IMPLICIT_RANK)
.setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
.build()
@@ -184,7 +184,7 @@
.setIndexingType(AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_EXACT_TERMS)
.build()
- ).addProperty(new AppSearchSchema.Int64PropertyConfig.Builder(KEY_ICON_RES_ID)
+ ).addProperty(new AppSearchSchema.LongPropertyConfig.Builder(KEY_ICON_RES_ID)
.setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
.build()
diff --git a/core/java/android/content/pm/ComponentInfo.java b/core/java/android/content/pm/ComponentInfo.java
index c67d00e..42847c8 100644
--- a/core/java/android/content/pm/ComponentInfo.java
+++ b/core/java/android/content/pm/ComponentInfo.java
@@ -16,8 +16,14 @@
package android.content.pm;
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.app.Service;
import android.compat.annotation.UnsupportedAppUsage;
+import android.content.BroadcastReceiver;
import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Parcel;
@@ -52,6 +58,25 @@
public String splitName;
/**
+ * Set of attribution tags that should be automatically applied to this
+ * component.
+ * <p>
+ * When this component represents an {@link Activity}, {@link Service},
+ * {@link ContentResolver} or {@link BroadcastReceiver}, each instance will
+ * be automatically configured with {@link Context#createAttributionContext}
+ * using the first attribution tag contained here.
+ * <p>
+ * Additionally, when this component represents a {@link BroadcastReceiver}
+ * and the sender of a broadcast requires the receiver to hold one or more
+ * specific permissions, those permission checks will be performed using
+ * each of the attributions tags contained here.
+ *
+ * @see Context#createAttributionContext(String)
+ */
+ @SuppressLint({"MissingNullability", "MutableBareField"})
+ public String[] attributionTags;
+
+ /**
* A string resource identifier (in the package's resources) containing
* a user-readable description of the component. From the "description"
* attribute or, if not set, 0.
@@ -87,6 +112,7 @@
applicationInfo = orig.applicationInfo;
processName = orig.processName;
splitName = orig.splitName;
+ attributionTags = orig.attributionTags;
descriptionRes = orig.descriptionRes;
enabled = orig.enabled;
exported = orig.exported;
@@ -172,6 +198,15 @@
if (splitName != null) {
pw.println(prefix + "splitName=" + splitName);
}
+ if (attributionTags != null && attributionTags.length > 0) {
+ StringBuilder tags = new StringBuilder();
+ tags.append(attributionTags[0]);
+ for (int i = 1; i < attributionTags.length; i++) {
+ tags.append(", ");
+ tags.append(attributionTags[i]);
+ }
+ pw.println(prefix + "attributionTags=[" + tags + "]");
+ }
pw.println(prefix + "enabled=" + enabled + " exported=" + exported
+ " directBootAware=" + directBootAware);
if (descriptionRes != 0) {
@@ -200,6 +235,7 @@
applicationInfo.writeToParcel(dest, parcelableFlags);
dest.writeString8(processName);
dest.writeString8(splitName);
+ dest.writeString8Array(attributionTags);
dest.writeInt(descriptionRes);
dest.writeInt(enabled ? 1 : 0);
dest.writeInt(exported ? 1 : 0);
@@ -211,6 +247,7 @@
applicationInfo = ApplicationInfo.CREATOR.createFromParcel(source);
processName = source.readString8();
splitName = source.readString8();
+ attributionTags = source.createString8Array();
descriptionRes = source.readInt();
enabled = (source.readInt() != 0);
exported = (source.readInt() != 0);
diff --git a/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java b/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java
index a9d70c5..d407b10 100644
--- a/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java
+++ b/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java
@@ -713,6 +713,7 @@
componentInfo.directBootAware = mainComponent.isDirectBootAware();
componentInfo.enabled = mainComponent.isEnabled();
componentInfo.splitName = mainComponent.getSplitName();
+ componentInfo.attributionTags = mainComponent.getAttributionTags();
}
private static void assignSharedFieldsForPackageItemInfo(
diff --git a/core/java/android/content/pm/parsing/ParsingPackageUtils.java b/core/java/android/content/pm/parsing/ParsingPackageUtils.java
index 5d74e74..022ba16 100644
--- a/core/java/android/content/pm/parsing/ParsingPackageUtils.java
+++ b/core/java/android/content/pm/parsing/ParsingPackageUtils.java
@@ -2816,15 +2816,7 @@
}
}
- @SuppressWarnings("AndroidFrameworkCompatChange")
private void convertSplitPermissions(ParsingPackage pkg) {
- // STOPSHIP(b/183905675): REMOVE THIS TERRIBLE, HORRIBLE, NO GOOD, VERY BAD HACK
- if ("com.android.chrome".equals(pkg.getPackageName())
- && pkg.getVersionCode() <= 445500399
- && pkg.getTargetSdkVersion() > Build.VERSION_CODES.R) {
- pkg.setTargetSdkVersion(Build.VERSION_CODES.R);
- }
-
final int listSize = mSplitPermissionInfos.size();
for (int is = 0; is < listSize; is++) {
final PermissionManager.SplitPermissionInfo spi = mSplitPermissionInfos.get(is);
diff --git a/core/java/android/content/pm/parsing/component/ParsedActivity.java b/core/java/android/content/pm/parsing/component/ParsedActivity.java
index 9285ccb..6f478ac 100644
--- a/core/java/android/content/pm/parsing/component/ParsedActivity.java
+++ b/core/java/android/content/pm/parsing/component/ParsedActivity.java
@@ -82,9 +82,6 @@
@Nullable
ActivityInfo.WindowLayout windowLayout;
- @Nullable
- String[] attributionTags;
-
public ParsedActivity(ParsedActivity other) {
super(other);
this.theme = other.theme;
@@ -110,7 +107,6 @@
this.rotationAnimation = other.rotationAnimation;
this.colorMode = other.colorMode;
this.windowLayout = other.windowLayout;
- this.attributionTags = other.attributionTags;
}
/**
@@ -176,7 +172,6 @@
alias.requestedVrComponent = target.requestedVrComponent;
alias.directBootAware = target.directBootAware;
alias.setProcessName(target.getProcessName());
- alias.attributionTags = target.attributionTags;
return alias;
// Not all attributes from the target ParsedActivity are copied to the alias.
@@ -304,7 +299,6 @@
} else {
dest.writeBoolean(false);
}
- dest.writeString8Array(this.attributionTags);
}
public ParsedActivity() {
@@ -338,7 +332,6 @@
if (in.readBoolean()) {
windowLayout = new ActivityInfo.WindowLayout(in);
}
- this.attributionTags = in.createString8Array();
}
public static final Parcelable.Creator<ParsedActivity> CREATOR = new Creator<ParsedActivity>() {
@@ -452,9 +445,4 @@
public ActivityInfo.WindowLayout getWindowLayout() {
return windowLayout;
}
-
- @Nullable
- public String[] getAttributionTags() {
- return attributionTags;
- }
}
diff --git a/core/java/android/content/pm/parsing/component/ParsedActivityUtils.java b/core/java/android/content/pm/parsing/component/ParsedActivityUtils.java
index aa740bd..92a90e9 100644
--- a/core/java/android/content/pm/parsing/component/ParsedActivityUtils.java
+++ b/core/java/android/content/pm/parsing/component/ParsedActivityUtils.java
@@ -102,7 +102,8 @@
R.styleable.AndroidManifestActivity_name,
R.styleable.AndroidManifestActivity_process,
R.styleable.AndroidManifestActivity_roundIcon,
- R.styleable.AndroidManifestActivity_splitName);
+ R.styleable.AndroidManifestActivity_splitName,
+ R.styleable.AndroidManifestActivity_attributionTags);
if (result.isError()) {
return result;
}
@@ -212,11 +213,6 @@
pkg.setVisibleToInstantApps(true);
}
- String attributionTags = sa.getString(R.styleable.AndroidManifestActivity_attributionTags);
- if (attributionTags != null) {
- activity.attributionTags = attributionTags.split("\\|");
- }
-
return parseActivityOrAlias(activity, pkg, tag, parser, res, sa, receiver,
false /*isAlias*/, visibleToEphemeral, input,
R.styleable.AndroidManifestActivity_parentActivityName,
@@ -281,7 +277,8 @@
R.styleable.AndroidManifestActivityAlias_name,
null /*processAttr*/,
R.styleable.AndroidManifestActivityAlias_roundIcon,
- null /*splitNameAttr*/);
+ null /*splitNameAttr*/,
+ R.styleable.AndroidManifestActivityAlias_attributionTags);
if (result.isError()) {
return result;
}
diff --git a/core/java/android/content/pm/parsing/component/ParsedMainComponent.java b/core/java/android/content/pm/parsing/component/ParsedMainComponent.java
index a5e394d..033e30f 100644
--- a/core/java/android/content/pm/parsing/component/ParsedMainComponent.java
+++ b/core/java/android/content/pm/parsing/component/ParsedMainComponent.java
@@ -39,6 +39,8 @@
@Nullable
String splitName;
+ @Nullable
+ String[] attributionTags;
public ParsedMainComponent() {
}
@@ -51,6 +53,7 @@
this.exported = other.exported;
this.order = other.order;
this.splitName = other.splitName;
+ this.attributionTags = other.attributionTags;
}
public ParsedMainComponent setProcessName(String processName) {
@@ -84,6 +87,7 @@
dest.writeBoolean(this.exported);
dest.writeInt(this.order);
dest.writeString(this.splitName);
+ dest.writeString8Array(this.attributionTags);
}
protected ParsedMainComponent(Parcel in) {
@@ -94,6 +98,7 @@
this.exported = in.readBoolean();
this.order = in.readInt();
this.splitName = in.readString();
+ this.attributionTags = in.createString8Array();
}
public static final Parcelable.Creator<ParsedMainComponent> CREATOR =
@@ -135,6 +140,11 @@
return splitName;
}
+ @Nullable
+ public String[] getAttributionTags() {
+ return attributionTags;
+ }
+
public ParsedMainComponent setDirectBootAware(boolean value) {
directBootAware = value;
return this;
@@ -149,4 +159,9 @@
splitName = value;
return this;
}
+
+ public ParsedMainComponent setAttributionTags(@Nullable String[] value) {
+ attributionTags = value;
+ return this;
+ }
}
diff --git a/core/java/android/content/pm/parsing/component/ParsedMainComponentUtils.java b/core/java/android/content/pm/parsing/component/ParsedMainComponentUtils.java
index f70d62b..54bcbdd 100644
--- a/core/java/android/content/pm/parsing/component/ParsedMainComponentUtils.java
+++ b/core/java/android/content/pm/parsing/component/ParsedMainComponentUtils.java
@@ -48,7 +48,8 @@
TypedArray array, int flags, boolean useRoundIcon, ParseInput input,
int bannerAttr, int descriptionAttr, @Nullable Integer directBootAwareAttr,
@Nullable Integer enabledAttr, int iconAttr, int labelAttr, int logoAttr, int nameAttr,
- @Nullable Integer processAttr, int roundIconAttr, @Nullable Integer splitNameAttr) {
+ @Nullable Integer processAttr, int roundIconAttr, @Nullable Integer splitNameAttr,
+ @Nullable Integer attributionTagsAttr) {
ParseResult<Component> result = ParsedComponentUtils.parseComponent(component, tag, pkg,
array, useRoundIcon, input, bannerAttr, descriptionAttr, iconAttr, labelAttr,
logoAttr, nameAttr, roundIconAttr);
@@ -94,6 +95,13 @@
component.splitName = array.getNonConfigurationString(splitNameAttr, 0);
}
+ if (attributionTagsAttr != null) {
+ final String attributionTags = array.getNonConfigurationString(attributionTagsAttr, 0);
+ if (attributionTags != null) {
+ component.attributionTags = attributionTags.split("\\|");
+ }
+ }
+
return input.success(component);
}
diff --git a/core/java/android/content/pm/parsing/component/ParsedProviderUtils.java b/core/java/android/content/pm/parsing/component/ParsedProviderUtils.java
index 4deab56..28fd919 100644
--- a/core/java/android/content/pm/parsing/component/ParsedProviderUtils.java
+++ b/core/java/android/content/pm/parsing/component/ParsedProviderUtils.java
@@ -74,7 +74,8 @@
R.styleable.AndroidManifestProvider_name,
R.styleable.AndroidManifestProvider_process,
R.styleable.AndroidManifestProvider_roundIcon,
- R.styleable.AndroidManifestProvider_splitName);
+ R.styleable.AndroidManifestProvider_splitName,
+ R.styleable.AndroidManifestProvider_attributionTags);
if (result.isError()) {
return result;
}
diff --git a/core/java/android/content/pm/parsing/component/ParsedServiceUtils.java b/core/java/android/content/pm/parsing/component/ParsedServiceUtils.java
index 739bee2..ae107ce 100644
--- a/core/java/android/content/pm/parsing/component/ParsedServiceUtils.java
+++ b/core/java/android/content/pm/parsing/component/ParsedServiceUtils.java
@@ -68,7 +68,8 @@
R.styleable.AndroidManifestService_name,
R.styleable.AndroidManifestService_process,
R.styleable.AndroidManifestService_roundIcon,
- R.styleable.AndroidManifestService_splitName
+ R.styleable.AndroidManifestService_splitName,
+ R.styleable.AndroidManifestService_attributionTags
);
if (result.isError()) {
diff --git a/core/java/android/content/res/ColorStateList.java b/core/java/android/content/res/ColorStateList.java
index 45b956b..5b727cc 100644
--- a/core/java/android/content/res/ColorStateList.java
+++ b/core/java/android/content/res/ColorStateList.java
@@ -35,6 +35,7 @@
import com.android.internal.R;
import com.android.internal.graphics.ColorUtils;
+import com.android.internal.graphics.cam.Cam;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.GrowingArrayUtils;
@@ -555,9 +556,8 @@
final int alpha = MathUtils.constrain((int) (baseAlpha * alphaMod + 0.5f), 0, 255);
if (validLStar) {
- final double[] labColor = new double[3];
- ColorUtils.colorToLAB(baseColor, labColor);
- baseColor = ColorUtils.LABToColor(lStar, labColor[1], labColor[2]);
+ final Cam baseCam = ColorUtils.colorToCAM(baseColor);
+ baseColor = ColorUtils.CAMToColor(baseCam.getHue(), baseCam.getChroma(), lStar);
}
return (baseColor & 0xFFFFFF) | (alpha << 24);
diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl
index dc3b88a..12937b5 100644
--- a/core/java/android/net/INetworkStatsService.aidl
+++ b/core/java/android/net/INetworkStatsService.aidl
@@ -65,8 +65,8 @@
/** Increment data layer count of operations performed for UID and tag. */
void incrementOperationCount(int uid, int tag, int operationCount);
- /** Force update of ifaces. */
- void forceUpdateIfaces(
+ /** Notify {@code NetworkStatsService} about network status changed. */
+ void notifyNetworkStatus(
in Network[] defaultNetworks,
in NetworkStateSnapshot[] snapshots,
in String activeIface,
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index 7ebb646..d8050ed 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -34,6 +34,8 @@
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.Signature;
+import android.net.ConnectivityAnnotations.MultipathPreference;
+import android.net.ConnectivityAnnotations.RestrictBackgroundStatus;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.os.Build;
@@ -463,6 +465,7 @@
*/
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
@RequiresPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK)
+ @RestrictBackgroundStatus
public int getRestrictBackgroundStatus(int uid) {
try {
return mService.getRestrictBackgroundStatus(uid);
@@ -588,6 +591,7 @@
*/
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
@RequiresPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK)
+ @MultipathPreference
public int getMultipathPreference(@NonNull Network network) {
try {
return mService.getMultipathPreference(network);
diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java
index d3c8957..fd446cd 100644
--- a/core/java/android/net/NetworkTemplate.java
+++ b/core/java/android/net/NetworkTemplate.java
@@ -274,11 +274,14 @@
}
/**
- * Template to match all carrier networks with the given IMSI.
+ * Template to match all metered carrier networks with the given IMSI.
*/
- public static NetworkTemplate buildTemplateCarrier(@NonNull String subscriberId) {
+ public static NetworkTemplate buildTemplateCarrierMetered(@NonNull String subscriberId) {
Objects.requireNonNull(subscriberId);
- return new NetworkTemplate(MATCH_CARRIER, subscriberId, null);
+ return new NetworkTemplate(MATCH_CARRIER, subscriberId,
+ new String[] { subscriberId }, null /* networkId */, METERED_YES, ROAMING_ALL,
+ DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL,
+ SUBSCRIBER_ID_MATCH_RULE_EXACT);
}
private final int mMatchRule;
diff --git a/core/java/android/net/vcn/VcnManager.java b/core/java/android/net/vcn/VcnManager.java
index 9d1c1ff..390c3b9 100644
--- a/core/java/android/net/vcn/VcnManager.java
+++ b/core/java/android/net/vcn/VcnManager.java
@@ -74,6 +74,36 @@
public class VcnManager {
@NonNull private static final String TAG = VcnManager.class.getSimpleName();
+ /**
+ * Key for WiFi entry RSSI thresholds
+ *
+ * <p>The VCN will only migrate to a Carrier WiFi network that has a signal strength greater
+ * than, or equal to this threshold.
+ *
+ * <p>WARNING: The VCN does not listen for changes to this key made after VCN startup.
+ *
+ * @hide
+ */
+ @NonNull
+ public static final String VCN_NETWORK_SELECTION_WIFI_ENTRY_RSSI_THRESHOLD_KEY =
+ "vcn_network_selection_wifi_entry_rssi_threshold";
+
+ /**
+ * Key for WiFi entry RSSI thresholds
+ *
+ * <p>If the VCN's selected Carrier WiFi network has a signal strength less than this threshold,
+ * the VCN will attempt to migrate away from the Carrier WiFi network.
+ *
+ * <p>WARNING: The VCN does not listen for changes to this key made after VCN startup.
+ *
+ * @hide
+ */
+ @NonNull
+ public static final String VCN_NETWORK_SELECTION_WIFI_EXIT_RSSI_THRESHOLD_KEY =
+ "vcn_network_selection_wifi_exit_rssi_threshold";
+
+ // TODO: Add separate signal strength thresholds for 2.4 GHz and 5GHz
+
private static final Map<
VcnNetworkPolicyChangeListener, VcnUnderlyingNetworkPolicyListenerBinder>
REGISTERED_POLICY_LISTENERS = new ConcurrentHashMap<>();
diff --git a/core/java/android/net/vcn/VcnTransportInfo.java b/core/java/android/net/vcn/VcnTransportInfo.java
index 1f18184..25a2574 100644
--- a/core/java/android/net/vcn/VcnTransportInfo.java
+++ b/core/java/android/net/vcn/VcnTransportInfo.java
@@ -16,11 +16,12 @@
package android.net.vcn;
-import static android.net.NetworkCapabilities.REDACT_NONE;
+import static android.net.NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS;
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.net.NetworkCapabilities;
import android.net.TransportInfo;
import android.net.wifi.WifiInfo;
import android.os.Parcel;
@@ -108,13 +109,24 @@
@Override
@NonNull
public TransportInfo makeCopy(long redactions) {
+ if ((redactions & NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS) != 0) {
+ return new VcnTransportInfo(null, INVALID_SUBSCRIPTION_ID);
+ }
+
return new VcnTransportInfo(
(mWifiInfo == null) ? null : mWifiInfo.makeCopy(redactions), mSubId);
}
@Override
public long getApplicableRedactions() {
- return (mWifiInfo == null) ? REDACT_NONE : mWifiInfo.getApplicableRedactions();
+ long redactions = REDACT_FOR_NETWORK_SETTINGS;
+
+ // Add additional wifi redactions if necessary
+ if (mWifiInfo != null) {
+ redactions |= mWifiInfo.getApplicableRedactions();
+ }
+
+ return redactions;
}
/** {@inheritDoc} */
@@ -135,6 +147,14 @@
public VcnTransportInfo createFromParcel(Parcel in) {
final int subId = in.readInt();
final WifiInfo wifiInfo = in.readParcelable(null);
+
+ // If all fields are their null values, return null TransportInfo to avoid
+ // leaking information about this being a VCN Network (instead of macro
+ // cellular, etc)
+ if (wifiInfo == null && subId == INVALID_SUBSCRIPTION_ID) {
+ return null;
+ }
+
return new VcnTransportInfo(wifiInfo, subId);
}
diff --git a/core/java/android/os/BatteryUsageStats.java b/core/java/android/os/BatteryUsageStats.java
index 3225667..8f36663 100644
--- a/core/java/android/os/BatteryUsageStats.java
+++ b/core/java/android/os/BatteryUsageStats.java
@@ -75,8 +75,10 @@
public static final int AGGREGATE_BATTERY_CONSUMER_SCOPE_COUNT = 2;
private final int mDischargePercentage;
- private final long mStatsStartTimestampMs;
private final double mBatteryCapacityMah;
+ private final long mStatsStartTimestampMs;
+ private final long mStatsEndTimestampMs;
+ private final long mStatsDurationMs;
private final double mDischargedPowerLowerBound;
private final double mDischargedPowerUpperBound;
private final long mBatteryTimeRemainingMs;
@@ -90,6 +92,12 @@
private BatteryUsageStats(@NonNull Builder builder) {
mStatsStartTimestampMs = builder.mStatsStartTimestampMs;
+ mStatsEndTimestampMs = builder.mStatsEndTimestampMs;
+ if (builder.mStatsDurationMs != -1) {
+ mStatsDurationMs = builder.mStatsDurationMs;
+ } else {
+ mStatsDurationMs = mStatsEndTimestampMs - mStatsStartTimestampMs;
+ }
mBatteryCapacityMah = builder.mBatteryCapacityMah;
mDischargePercentage = builder.mDischargePercentage;
mDischargedPowerLowerBound = builder.mDischargedPowerLowerBoundMah;
@@ -141,6 +149,24 @@
}
/**
+ * Timestamp (as returned by System.currentTimeMillis()) of when the stats snapshot was taken,
+ * in milliseconds.
+ */
+ public long getStatsEndTimestamp() {
+ return mStatsEndTimestampMs;
+ }
+
+ /**
+ * Returns the duration of the stats session captured by this BatteryUsageStats.
+ * In rare cases, statsDuration != statsEndTimestamp - statsStartTimestamp. This may
+ * happen when BatteryUsageStats represents an accumulation of data across multiple
+ * non-contiguous sessions.
+ */
+ public long getStatsDuration() {
+ return mStatsDurationMs;
+ }
+
+ /**
* Total amount of battery charge drained since BatteryStats reset (e.g. due to being fully
* charged), in mAh
*/
@@ -229,6 +255,8 @@
private BatteryUsageStats(@NonNull Parcel source) {
mStatsStartTimestampMs = source.readLong();
+ mStatsEndTimestampMs = source.readLong();
+ mStatsDurationMs = source.readLong();
mBatteryCapacityMah = source.readDouble();
mDischargePercentage = source.readInt();
mDischargedPowerLowerBound = source.readDouble();
@@ -287,6 +315,8 @@
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeLong(mStatsStartTimestampMs);
+ dest.writeLong(mStatsEndTimestampMs);
+ dest.writeLong(mStatsDurationMs);
dest.writeDouble(mBatteryCapacityMah);
dest.writeInt(mDischargePercentage);
dest.writeDouble(mDischargedPowerLowerBound);
@@ -441,6 +471,8 @@
private final String[] mCustomPowerComponentNames;
private final boolean mIncludePowerModels;
private long mStatsStartTimestampMs;
+ private long mStatsEndTimestampMs;
+ private long mStatsDurationMs = -1;
private double mBatteryCapacityMah;
private int mDischargePercentage;
private double mDischargedPowerLowerBoundMah;
@@ -494,6 +526,23 @@
}
/**
+ * Sets the timestamp of when the battery stats snapshot was taken, in milliseconds.
+ */
+ public Builder setStatsEndTimestamp(long statsEndTimestampMs) {
+ mStatsEndTimestampMs = statsEndTimestampMs;
+ return this;
+ }
+
+ /**
+ * Sets the duration of the stats session. The default value of this field is
+ * statsEndTimestamp - statsStartTimestamp.
+ */
+ public Builder setStatsDuration(long statsDurationMs) {
+ mStatsDurationMs = statsDurationMs;
+ return this;
+ }
+
+ /**
* Sets the battery discharge amount since BatteryStats reset as percentage of the full
* charge.
*/
diff --git a/core/java/android/os/OWNERS b/core/java/android/os/OWNERS
index 6e99b0d..dfd935d0 100644
--- a/core/java/android/os/OWNERS
+++ b/core/java/android/os/OWNERS
@@ -67,3 +67,6 @@
# RecoverySystem
per-file *Recovery* = file:/services/core/java/com/android/server/recoverysystem/OWNERS
+
+# Bugreporting
+per-file Bugreport* = file:/platform/frameworks/native:/cmds/dumpstate/OWNERS
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 5f5a910..50f390b 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -680,13 +680,20 @@
/**
* Store or read an IBinder interface token in the parcel at the current
- * {@link #dataPosition}. This is used to validate that the marshalled
- * transaction is intended for the target interface.
+ * {@link #dataPosition}. This is used to validate that the marshalled
+ * transaction is intended for the target interface. This is typically written
+ * at the beginning of transactions as a header.
*/
public final void writeInterfaceToken(@NonNull String interfaceName) {
nativeWriteInterfaceToken(mNativePtr, interfaceName);
}
+ /**
+ * Read the header written by writeInterfaceToken and verify it matches
+ * the interface name in question. If the wrong interface type is present,
+ * {@link SecurityException} is thrown. When used over binder, this exception
+ * should propagate to the caller.
+ */
public final void enforceInterface(@NonNull String interfaceName) {
nativeEnforceInterface(mNativePtr, interfaceName);
}
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 326012d..5848d2f 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -189,6 +189,28 @@
public @interface QuietModeFlag {}
/**
+ * Flag returned by {@link #getUserPrivacySensitivity} to indicate that the user isn't
+ * particularly sensitive about a certain aspect of privacy.
+ */
+ public static final int PRIVACY_SENSITIVITY_DEFAULT = 0x0;
+
+ /**
+ * Flag returned by {@link #getUserPrivacySensitivity} to indicate that the user is sensitive
+ * about location privacy.
+ */
+ public static final int PRIVACY_SENSITIVITY_LOCATION = 0x1;
+
+ /**
+ * List of flags available for the {@link #getUserPrivacySensitivity} method.
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(flag = true, prefix = { "PRIVACY_SENSITIVITY_" }, value = {
+ PRIVACY_SENSITIVITY_DEFAULT,
+ PRIVACY_SENSITIVITY_LOCATION})
+ public @interface PrivacySensitivityFlag {}
+
+ /**
* @hide
* No user restriction.
*/
@@ -1286,6 +1308,40 @@
"disallow_config_private_dns";
/**
+ * Specifies whether the microphone toggle is available to the user. If this restriction is set,
+ * the user will not be able to block microphone access via the system toggle. If microphone
+ * access is blocked when the restriction is added, it will be automatically re-enabled.
+ *
+ * This restriction can only be set by a device owner.
+ *
+ * <p>The default value is <code>false</code>.
+ *
+ * @see android.hardware.SensorPrivacyManager
+ * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+ * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
+ * @see #getUserRestrictions()
+ */
+ public static final String DISALLOW_MICROPHONE_TOGGLE =
+ "disallow_microphone_toggle";
+
+ /**
+ * Specifies whether the camera toggle is available to the user. If this restriction is set,
+ * the user will not be able to block camera access via the system toggle. If camera
+ * access is blocked when the restriction is added, it will be automatically re-enabled.
+ *
+ * This restriction can only be set by a device owner.
+ *
+ * <p>The default value is <code>false</code>.
+ *
+ * @see android.hardware.SensorPrivacyManager
+ * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+ * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
+ * @see #getUserRestrictions()
+ */
+ public static final String DISALLOW_CAMERA_TOGGLE =
+ "disallow_camera_toggle";
+
+ /**
* Application restriction key that is used to indicate the pending arrival
* of real restrictions for the app.
*
@@ -1376,6 +1432,8 @@
DISALLOW_SHARE_INTO_MANAGED_PROFILE,
DISALLOW_PRINTING,
DISALLOW_CONFIG_PRIVATE_DNS,
+ DISALLOW_MICROPHONE_TOGGLE,
+ DISALLOW_CAMERA_TOGGLE,
KEY_RESTRICTIONS_PENDING,
})
@Retention(RetentionPolicy.SOURCE)
@@ -3902,6 +3960,17 @@
}
/**
+ * Get the privacy sensitivity of the user.
+ *
+ * @return the privacy sensitivity of the user
+ */
+ @PrivacySensitivityFlag
+ public int getUserPrivacySensitivity() {
+ // TODO: Add actual implementation.
+ return PRIVACY_SENSITIVITY_DEFAULT;
+ }
+
+ /**
* Returns whether the given user has a badge (generally to put on profiles' icons).
*
* @param userId userId of the user in question
diff --git a/core/java/android/os/Vibrator.java b/core/java/android/os/Vibrator.java
index 95962c8..12538e6 100644
--- a/core/java/android/os/Vibrator.java
+++ b/core/java/android/os/Vibrator.java
@@ -227,6 +227,17 @@
}
/**
+ * Check whether the vibrator can be controlled by an external service with the
+ * {@link IExternalVibratorService}.
+ *
+ * @return True if the hardware can be controlled by an external service, otherwise false.
+ * @hide
+ */
+ public boolean hasExternalControl() {
+ return getInfo().hasCapability(IVibrator.CAP_EXTERNAL_CONTROL);
+ }
+
+ /**
* Gets the resonant frequency of the vibrator.
*
* @return the resonant frequency of the vibrator, or {@link Float#NaN NaN} if it's unknown or
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index 1092adf..3daa3a5 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -31,6 +31,7 @@
import android.content.pm.PackageManager;
import android.database.ContentObserver;
import android.net.Uri;
+import android.provider.Settings.Config.SyncDisabledMode;
import android.provider.Settings.ResetMode;
import android.util.ArrayMap;
import android.util.Log;
@@ -585,8 +586,16 @@
*
* @hide
*/
+ @TestApi
public static final String NAMESPACE_CONSTRAIN_DISPLAY_APIS = "constrain_display_apis";
+ /**
+ * Trace error logger properties definitions.
+ *
+ * @hide
+ */
+ public static final String NAMESPACE_TRACE_ERROR_LOGGER = "trace_error_logger";
+
private static final Object sLock = new Object();
@GuardedBy("sLock")
private static ArrayMap<OnPropertiesChangedListener, Pair<String, Executor>> sListeners =
@@ -839,6 +848,37 @@
}
/**
+ * Disables or re-enables bulk modifications ({@link #setProperties(Properties)}) to device
+ * config values. This is intended for use during tests to prevent a sync operation clearing
+ * config values, which could influence the outcome of the tests, i.e. by changing behavior.
+ *
+ * @param syncDisabledMode the mode to use, see {@link Settings.Config#SYNC_DISABLED_MODE_NONE},
+ * {@link Settings.Config#SYNC_DISABLED_MODE_PERSISTENT} and {@link
+ * Settings.Config#SYNC_DISABLED_MODE_UNTIL_REBOOT}
+ *
+ * @see #isSyncDisabled()
+ * @hide
+ */
+ @RequiresPermission(WRITE_DEVICE_CONFIG)
+ public static void setSyncDisabled(@SyncDisabledMode int syncDisabledMode) {
+ ContentResolver contentResolver = ActivityThread.currentApplication().getContentResolver();
+ Settings.Config.setSyncDisabled(contentResolver, syncDisabledMode);
+ }
+
+ /**
+ * Returns the current state of sync disabling, {@code true} when disabled, {@code false}
+ * otherwise.
+ *
+ * @see #setSyncDisabled(int)
+ * @hide
+ */
+ @RequiresPermission(WRITE_DEVICE_CONFIG)
+ public static boolean isSyncDisabled() {
+ ContentResolver contentResolver = ActivityThread.currentApplication().getContentResolver();
+ return Settings.Config.isSyncDisabled(contentResolver);
+ }
+
+ /**
* Add a listener for property changes.
* <p>
* This listener will be called whenever properties in the specified namespace change. Callbacks
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index e410e50..0c23ae6 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -267,8 +267,40 @@
/** @hide */
public static final String EXTRA_NETWORK_TEMPLATE = "network_template";
+ /**
+ * The return values for {@link Settings.Config#set}
+ * @hide
+ */
+ @IntDef(prefix = "SET_ALL_RESULT_",
+ value = { SET_ALL_RESULT_FAILURE, SET_ALL_RESULT_SUCCESS, SET_ALL_RESULT_DISABLED })
+ @Retention(RetentionPolicy.SOURCE)
+ @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
+ public @interface SetAllResult {}
+
+ /**
+ * A return value for {@link #KEY_CONFIG_SET_ALL_RETURN}, indicates failure.
+ * @hide
+ */
+ public static final int SET_ALL_RESULT_FAILURE = 0;
+
+ /**
+ * A return value for {@link #KEY_CONFIG_SET_ALL_RETURN}, indicates success.
+ * @hide
+ */
+ public static final int SET_ALL_RESULT_SUCCESS = 1;
+
+ /**
+ * A return value for {@link #KEY_CONFIG_SET_ALL_RETURN}, indicates a set all is disabled.
+ * @hide
+ */
+ public static final int SET_ALL_RESULT_DISABLED = 2;
+
/** @hide */
- public static final String KEY_CONFIG_SET_RETURN = "config_set_return";
+ public static final String KEY_CONFIG_SET_ALL_RETURN = "config_set_all_return";
+
+ /** @hide */
+ public static final String KEY_CONFIG_IS_SYNC_DISABLED_RETURN =
+ "config_is_sync_disabled_return";
/**
* An int extra specifying a subscription ID.
@@ -890,6 +922,21 @@
"android.settings.LOCALE_SETTINGS";
/**
+ * Activity Action: Show settings to allow configuration of lockscreen.
+ * <p>
+ * In some cases, a matching Activity may not exist, so ensure you
+ * safeguard against this.
+ * <p>
+ * Input: Nothing.
+ * <p>
+ * Output: Nothing.
+ *
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_LOCKSCREEN_SETTINGS = "android.settings.LOCK_SCREEN_SETTINGS";
+
+ /**
* Activity Action: Show settings to configure input methods, in particular
* allowing the user to enable input methods.
* <p>
@@ -2324,6 +2371,11 @@
public static final String CALL_METHOD_PREFIX_KEY = "_prefix";
/**
+ * @hide - String argument extra to the fast-path call()-based requests
+ */
+ public static final String CALL_METHOD_SYNC_DISABLED_MODE_KEY = "_disabled_mode";
+
+ /**
* @hide - RemoteCallback monitor callback argument extra to the fast-path call()-based requests
*/
public static final String CALL_METHOD_MONITOR_CALLBACK_KEY = "_monitor_callback_key";
@@ -2386,6 +2438,15 @@
/** @hide - Private call() method to reset to defaults the 'configuration' table */
public static final String CALL_METHOD_LIST_CONFIG = "LIST_config";
+ /** @hide - Private call() method to disable / re-enable syncs to the 'configuration' table */
+ public static final String CALL_METHOD_SET_SYNC_DISABLED_CONFIG = "SET_SYNC_DISABLED_config";
+
+ /**
+ * @hide - Private call() method to return whether syncs are disabled for the 'configuration'
+ * table
+ */
+ public static final String CALL_METHOD_IS_SYNC_DISABLED_CONFIG = "IS_SYNC_DISABLED_config";
+
/** @hide - Private call() method to register monitor callback for 'configuration' table */
public static final String CALL_METHOD_REGISTER_MONITOR_CALLBACK_CONFIG =
"REGISTER_MONITOR_CALLBACK_config";
@@ -2762,11 +2823,11 @@
return true;
}
- public boolean setStringsForPrefix(ContentResolver cr, String prefix,
+ public @SetAllResult int setStringsForPrefix(ContentResolver cr, String prefix,
HashMap<String, String> keyValues) {
if (mCallSetAllCommand == null) {
// This NameValueCache does not support atomically setting multiple flags
- return false;
+ return SET_ALL_RESULT_FAILURE;
}
try {
Bundle args = new Bundle();
@@ -2776,10 +2837,10 @@
Bundle bundle = cp.call(cr.getAttributionSource(),
mProviderHolder.mUri.getAuthority(),
mCallSetAllCommand, null, args);
- return bundle.getBoolean(KEY_CONFIG_SET_RETURN);
+ return bundle.getInt(KEY_CONFIG_SET_ALL_RETURN);
} catch (RemoteException e) {
// Not supported by the remote side
- return false;
+ return SET_ALL_RESULT_FAILURE;
}
}
@@ -9454,6 +9515,20 @@
"power_menu_locked_show_content";
/**
+ * Whether home controls should be accessible from the lockscreen
+ *
+ * @hide
+ */
+ public static final String LOCKSCREEN_SHOW_CONTROLS = "lockscreen_show_controls";
+
+ /**
+ * Whether wallet should be accessible from the lockscreen
+ *
+ * @hide
+ */
+ public static final String LOCKSCREEN_SHOW_WALLET = "lockscreen_show_wallet";
+
+ /**
* Specifies whether the web action API is enabled.
*
* @hide
@@ -9985,6 +10060,12 @@
@Readable
public static final String NAS_SETTINGS_UPDATED = "nas_settings_updated";
+ /**
+ * Control whether Game Dashboard shortcut is always on for all games.
+ * @hide
+ */
+ @Readable
+ public static final String GAME_DASHBOARD_ALWAYS_ON = "game_dashboard_always_on";
/**
* These entries are considered common between the personal and the managed profile,
@@ -14199,6 +14280,15 @@
public static final String ARE_USER_DISABLED_HDR_FORMATS_ALLOWED =
"are_user_disabled_hdr_formats_allowed";
+ /**
+ * Whether or not syncs (bulk set operations) for {@link DeviceConfig} are disabled
+ * currently. The value is boolean (1 or 0). The value '1' means that {@link
+ * DeviceConfig#setProperties(DeviceConfig.Properties)} will return {@code false}.
+ *
+ * @hide
+ */
+ public static final String DEVICE_CONFIG_SYNC_DISABLED = "device_config_sync_disabled";
+
/** @hide */ public static String zenModeToString(int mode) {
if (mode == ZEN_MODE_IMPORTANT_INTERRUPTIONS) return "ZEN_MODE_IMPORTANT_INTERRUPTIONS";
if (mode == ZEN_MODE_ALARMS) return "ZEN_MODE_ALARMS";
@@ -16033,6 +16123,39 @@
* @hide
*/
public static final class Config extends NameValueTable {
+
+ /**
+ * The modes that can be used when disabling syncs to the 'config' settings.
+ * @hide
+ */
+ @IntDef(prefix = "DISABLE_SYNC_MODE_",
+ value = { SYNC_DISABLED_MODE_NONE, SYNC_DISABLED_MODE_PERSISTENT,
+ SYNC_DISABLED_MODE_UNTIL_REBOOT })
+ @Retention(RetentionPolicy.SOURCE)
+ @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
+ public @interface SyncDisabledMode {}
+
+ /**
+ * Sync is not not disabled.
+ *
+ * @hide
+ */
+ public static final int SYNC_DISABLED_MODE_NONE = 0;
+
+ /**
+ * Disabling of Config bulk update / syncing is persistent, i.e. it survives a device
+ * reboot.
+ * @hide
+ */
+ public static final int SYNC_DISABLED_MODE_PERSISTENT = 1;
+
+ /**
+ * Disabling of Config bulk update / syncing is not persistent, i.e. it will not survive a
+ * device reboot.
+ * @hide
+ */
+ public static final int SYNC_DISABLED_MODE_UNTIL_REBOOT = 2;
+
private static final ContentProviderHolder sProviderHolder =
new ContentProviderHolder(DeviceConfig.CONTENT_URI);
@@ -16125,7 +16248,7 @@
* @param resolver to access the database with.
* @param namespace to which the names should be set.
* @param keyValues map of key names (without the prefix) to values.
- * @return
+ * @return true if the name/value pairs were set, false if setting was blocked
*
* @hide
*/
@@ -16138,12 +16261,15 @@
compositeKeyValueMap.put(
createCompositeName(namespace, entry.getKey()), entry.getValue());
}
- // If can't set given configuration that means it's bad
- if (!sNameValueCache.setStringsForPrefix(resolver, createPrefix(namespace),
- compositeKeyValueMap)) {
- throw new DeviceConfig.BadConfigException();
+ int result = sNameValueCache.setStringsForPrefix(
+ resolver, createPrefix(namespace), compositeKeyValueMap);
+ if (result == SET_ALL_RESULT_SUCCESS) {
+ return true;
+ } else if (result == SET_ALL_RESULT_DISABLED) {
+ return false;
}
- return true;
+ // If can't set given configuration that means it's bad
+ throw new DeviceConfig.BadConfigException();
}
/**
@@ -16179,6 +16305,50 @@
}
/**
+ * Bridge method between {@link DeviceConfig#setSyncDisabled(int)} and the
+ * {@link com.android.providers.settings.SettingsProvider} implementation.
+ *
+ * @hide
+ */
+ @SuppressLint("AndroidFrameworkRequiresPermission")
+ @RequiresPermission(Manifest.permission.WRITE_DEVICE_CONFIG)
+ static void setSyncDisabled(
+ @NonNull ContentResolver resolver, @SyncDisabledMode int disableSyncMode) {
+ try {
+ Bundle args = new Bundle();
+ args.putInt(CALL_METHOD_SYNC_DISABLED_MODE_KEY, disableSyncMode);
+ IContentProvider cp = sProviderHolder.getProvider(resolver);
+ cp.call(resolver.getAttributionSource(),
+ sProviderHolder.mUri.getAuthority(), CALL_METHOD_SET_SYNC_DISABLED_CONFIG,
+ null, args);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Can't set sync disabled " + DeviceConfig.CONTENT_URI, e);
+ }
+ }
+
+ /**
+ * Bridge method between {@link DeviceConfig#isSyncDisabled()} and the
+ * {@link com.android.providers.settings.SettingsProvider} implementation.
+ *
+ * @hide
+ */
+ @SuppressLint("AndroidFrameworkRequiresPermission")
+ @RequiresPermission(Manifest.permission.WRITE_DEVICE_CONFIG)
+ static boolean isSyncDisabled(@NonNull ContentResolver resolver) {
+ try {
+ Bundle args = Bundle.EMPTY;
+ IContentProvider cp = sProviderHolder.getProvider(resolver);
+ Bundle bundle = cp.call(resolver.getAttributionSource(),
+ sProviderHolder.mUri.getAuthority(), CALL_METHOD_IS_SYNC_DISABLED_CONFIG,
+ null, args);
+ return bundle.getBoolean(KEY_CONFIG_IS_SYNC_DISABLED_RETURN);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Can't query sync disabled " + DeviceConfig.CONTENT_URI, e);
+ }
+ return false;
+ }
+
+ /**
* Register callback for monitoring Config table.
*
* @param resolver Handle to the content resolver.
diff --git a/core/java/android/service/autofill/FillRequest.java b/core/java/android/service/autofill/FillRequest.java
index af846b6..62becc5 100644
--- a/core/java/android/service/autofill/FillRequest.java
+++ b/core/java/android/service/autofill/FillRequest.java
@@ -96,8 +96,6 @@
*/
public static final @RequestFlags int FLAG_VIEW_NOT_FOCUSED = 0x10;
- // The flag value 0x20 has been defined in AutofillManager.
-
/** @hide */
public static final int INVALID_REQUEST_ID = Integer.MIN_VALUE;
diff --git a/core/java/android/service/displayhash/DisplayHashingService.java b/core/java/android/service/displayhash/DisplayHashingService.java
index e8bb485..f22d40e 100644
--- a/core/java/android/service/displayhash/DisplayHashingService.java
+++ b/core/java/android/service/displayhash/DisplayHashingService.java
@@ -51,15 +51,9 @@
public static final String EXTRA_VERIFIED_DISPLAY_HASH =
"android.service.displayhash.extra.VERIFIED_DISPLAY_HASH";
- /**
- * Name under which a DisplayHashingService component publishes information
- * about itself. This meta-data must reference an XML resource containing a
- * {@link com.android.internal.R.styleable#DisplayHashingService} tag.
- *
- * @hide
- */
- @SystemApi
- public static final String SERVICE_META_DATA = "android.displayhash.display_hashing_service";
+ /** @hide **/
+ public static final String EXTRA_INTERVAL_BETWEEN_REQUESTS =
+ "android.service.displayhash.extra.INTERVAL_BETWEEN_REQUESTS";
/**
* The {@link Intent} action that must be declared as handled by a service in its manifest
@@ -149,6 +143,21 @@
callback.sendResult(data);
}
+ /**
+ * Call to get the interval required between display hash requests. Requests made faster than
+ * this will be throttled.
+ *
+ * @return the interval value required between requests.
+ */
+ public abstract int onGetIntervalBetweenRequestsMillis();
+
+ private void getDurationBetweenRequestsMillis(RemoteCallback callback) {
+ int durationBetweenRequestMillis = onGetIntervalBetweenRequestsMillis();
+ Bundle data = new Bundle();
+ data.putInt(EXTRA_INTERVAL_BETWEEN_REQUESTS, durationBetweenRequestMillis);
+ callback.sendResult(data);
+ }
+
private final class DisplayHashingServiceWrapper extends IDisplayHashingService.Stub {
@Override
public void generateDisplayHash(byte[] salt, HardwareBuffer buffer, Rect bounds,
@@ -187,5 +196,12 @@
mHandler.sendMessage(obtainMessage(DisplayHashingService::getDisplayHashAlgorithms,
DisplayHashingService.this, callback));
}
+
+ @Override
+ public void getIntervalBetweenRequestsMillis(RemoteCallback callback) {
+ mHandler.sendMessage(
+ obtainMessage(DisplayHashingService::getDurationBetweenRequestsMillis,
+ DisplayHashingService.this, callback));
+ }
}
}
diff --git a/core/java/android/service/displayhash/IDisplayHashingService.aidl b/core/java/android/service/displayhash/IDisplayHashingService.aidl
index 56e1e0a..066cd51 100644
--- a/core/java/android/service/displayhash/IDisplayHashingService.aidl
+++ b/core/java/android/service/displayhash/IDisplayHashingService.aidl
@@ -58,4 +58,13 @@
* @param callback The callback invoked to send back the map of algorithms to DisplayHashParams.
*/
void getDisplayHashAlgorithms(in RemoteCallback callback);
+
+ /**
+ * Call to get the interval required between display hash requests. Requests made faster than
+ * this will be throttled. The result will be sent in the callback as an int with the key
+ * {@link #EXTRA_INTERVAL_BETWEEN_REQUESTS}.
+ *
+ * @param callback The callback invoked to send back the interval duration.
+ */
+ void getIntervalBetweenRequestsMillis(in RemoteCallback callback);
}
diff --git a/core/java/android/service/notification/StatusBarNotification.java b/core/java/android/service/notification/StatusBarNotification.java
index 8e4a68e..863d71f 100644
--- a/core/java/android/service/notification/StatusBarNotification.java
+++ b/core/java/android/service/notification/StatusBarNotification.java
@@ -434,11 +434,8 @@
public Context getPackageContext(Context context) {
if (mContext == null) {
try {
- ApplicationInfo ai = context.getPackageManager()
- .getApplicationInfoAsUser(pkg, PackageManager.MATCH_UNINSTALLED_PACKAGES,
- getUserId());
- mContext = context.createApplicationContext(ai,
- Context.CONTEXT_RESTRICTED);
+ mContext = context.createPackageContextAsUser(pkg, Context.CONTEXT_RESTRICTED, user,
+ PackageManager.MATCH_UNINSTALLED_PACKAGES);
} catch (PackageManager.NameNotFoundException e) {
mContext = null;
}
diff --git a/core/java/android/service/quickaccesswallet/QuickAccessWalletClientImpl.java b/core/java/android/service/quickaccesswallet/QuickAccessWalletClientImpl.java
index 9d0b582..2e4af3f 100644
--- a/core/java/android/service/quickaccesswallet/QuickAccessWalletClientImpl.java
+++ b/core/java/android/service/quickaccesswallet/QuickAccessWalletClientImpl.java
@@ -61,6 +61,7 @@
public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, ServiceConnection {
private static final String TAG = "QAWalletSClient";
+ public static final String SETTING_KEY = "lockscreen_show_wallet";
private final Handler mHandler;
private final Context mContext;
private final Queue<ApiCaller> mRequestQueue;
@@ -96,13 +97,12 @@
int currentUser = ActivityManager.getCurrentUser();
return currentUser == UserHandle.USER_SYSTEM
&& checkUserSetupComplete()
- && checkSecureSetting(Settings.Secure.GLOBAL_ACTIONS_PANEL_ENABLED)
&& !new LockPatternUtils(mContext).isUserInLockdown(currentUser);
}
@Override
public boolean isWalletFeatureAvailableWhenDeviceLocked() {
- return checkSecureSetting(Settings.Secure.POWER_MENU_LOCKED_SHOW_CONTENT);
+ return checkSecureSetting(SETTING_KEY);
}
@Override
diff --git a/core/java/android/service/translation/OnTranslationResultCallbackWrapper.java b/core/java/android/service/translation/OnTranslationResultCallbackWrapper.java
index f585155..4f881b8 100644
--- a/core/java/android/service/translation/OnTranslationResultCallbackWrapper.java
+++ b/core/java/android/service/translation/OnTranslationResultCallbackWrapper.java
@@ -17,7 +17,6 @@
package android.service.translation;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.os.DeadObjectException;
import android.os.RemoteException;
import android.util.Log;
@@ -25,6 +24,7 @@
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.Consumer;
/**
* Callback to receive the {@link TranslationResponse} on successful translation.
@@ -32,13 +32,13 @@
* @hide
*/
final class OnTranslationResultCallbackWrapper implements
- TranslationService.OnTranslationResultCallback {
+ Consumer<TranslationResponse> {
private static final String TAG = "OnTranslationResultCallback";
private final @NonNull ITranslationCallback mCallback;
- private AtomicBoolean mCalled;
+ private final AtomicBoolean mCalled;
/**
* @hide
@@ -49,7 +49,7 @@
}
@Override
- public void onTranslationSuccess(@Nullable TranslationResponse response) {
+ public void accept(TranslationResponse response) {
assertNotCalled();
if (mCalled.getAndSet(response.isFinalResponse())) {
throw new IllegalStateException("Already called with complete response");
@@ -66,15 +66,6 @@
}
}
- /**
- * @deprecated use {@link #onTranslationSuccess} with error response instead.
- */
- @Override
- @Deprecated
- public void onError() {
- // no-op.
- }
-
private void assertNotCalled() {
if (mCalled.get()) {
throw new IllegalStateException("Already called");
diff --git a/core/java/android/service/translation/TranslationService.java b/core/java/android/service/translation/TranslationService.java
index e7234cc..24ebe45 100644
--- a/core/java/android/service/translation/TranslationService.java
+++ b/core/java/android/service/translation/TranslationService.java
@@ -125,7 +125,9 @@
/**
* Interface definition for a callback to be invoked when the translation is compleled.
+ * @deprecated use a {@link Consumer} instead.
*/
+ @Deprecated
public interface OnTranslationResultCallback {
/**
* Notifies the Android System that a translation request
@@ -162,12 +164,12 @@
public void onTranslationRequest(TranslationRequest request, int sessionId,
ICancellationSignal transport, ITranslationCallback callback)
throws RemoteException {
- final OnTranslationResultCallback translationResultCallback =
+ final Consumer<TranslationResponse> consumer =
new OnTranslationResultCallbackWrapper(callback);
mHandler.sendMessage(obtainMessage(TranslationService::onTranslationRequest,
TranslationService.this, request, sessionId,
CancellationSignal.fromTransport(transport),
- translationResultCallback));
+ consumer));
}
@Override
@@ -242,8 +244,10 @@
* instead.
*/
@Deprecated
- public abstract void onCreateTranslationSession(@NonNull TranslationContext translationContext,
- int sessionId);
+ public void onCreateTranslationSession(@NonNull TranslationContext translationContext,
+ int sessionId) {
+ // no-op
+ }
/**
* TODO: fill in javadoc.
@@ -259,10 +263,45 @@
* @param sessionId
* @param callback
* @param cancellationSignal
+ * @deprecated use
+ * {@link #onTranslationRequest(TranslationRequest, int, CancellationSignal, Consumer)} instead.
*/
- public abstract void onTranslationRequest(@NonNull TranslationRequest request, int sessionId,
+ @Deprecated
+ public void onTranslationRequest(@NonNull TranslationRequest request, int sessionId,
@Nullable CancellationSignal cancellationSignal,
- @NonNull OnTranslationResultCallback callback);
+ @NonNull OnTranslationResultCallback callback) {
+ // no-op
+ }
+
+ /**
+ * Called to the service with a {@link TranslationRequest} to be translated.
+ *
+ * <p>The service must call {@code callback.accept()} with the {@link TranslationResponse}. If
+ * {@link TranslationRequest#FLAG_PARTIAL_RESPONSES} was set, the service may call
+ * {@code callback.accept()} multiple times with partial responses.</p>
+ *
+ * @param request
+ * @param sessionId
+ * @param callback
+ * @param cancellationSignal
+ */
+ //TODO: make abstract once aiai transitions.
+ public void onTranslationRequest(@NonNull TranslationRequest request, int sessionId,
+ @Nullable CancellationSignal cancellationSignal,
+ @NonNull Consumer<TranslationResponse> callback) {
+ onTranslationRequest(request, sessionId, cancellationSignal,
+ new OnTranslationResultCallback() {
+ @Override
+ public void onTranslationSuccess(@NonNull TranslationResponse response) {
+ callback.accept(response);
+ }
+
+ @Override
+ public void onError() {
+ // null-op
+ }
+ });
+ }
/**
* TODO: fill in javadoc
diff --git a/core/java/android/service/voice/AlwaysOnHotwordDetector.java b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
index e813017..fed28df 100644
--- a/core/java/android/service/voice/AlwaysOnHotwordDetector.java
+++ b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
@@ -49,7 +49,6 @@
import android.os.PersistableBundle;
import android.os.RemoteException;
import android.os.SharedMemory;
-import android.service.voice.HotwordDetectionService.InitializationStatus;
import android.util.Log;
import android.util.Slog;
@@ -531,9 +530,12 @@
* Called when the {@link HotwordDetectionService} is created by the system and given a
* short amount of time to report it's initialization state.
*
- * @param status Info about initialization state of {@link HotwordDetectionService}.
+ * @param status Info about initialization state of {@link HotwordDetectionService}; the
+ * allowed values are {@link HotwordDetectionService#INITIALIZATION_STATUS_SUCCESS},
+ * 1<->{@link HotwordDetectionService#getMaxCustomInitializationStatus()},
+ * {@link HotwordDetectionService#INITIALIZATION_STATUS_UNKNOWN}.
*/
- public void onHotwordDetectionServiceInitialized(@InitializationStatus int status) {
+ public void onHotwordDetectionServiceInitialized(int status) {
}
/**
diff --git a/core/java/android/service/voice/HotwordDetectionService.java b/core/java/android/service/voice/HotwordDetectionService.java
index ea01e09..3960e38 100644
--- a/core/java/android/service/voice/HotwordDetectionService.java
+++ b/core/java/android/service/voice/HotwordDetectionService.java
@@ -78,15 +78,12 @@
/** @hide */
public static final String KEY_INITIALIZATION_STATUS = "initialization_status";
- /** @hide */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(flag = true, prefix = { "INITIALIZATION_STATUS_" }, value = {
- INITIALIZATION_STATUS_SUCCESS,
- INITIALIZATION_STATUS_CUSTOM_ERROR_1,
- INITIALIZATION_STATUS_CUSTOM_ERROR_2,
- INITIALIZATION_STATUS_UNKNOWN,
- })
- public @interface InitializationStatus {}
+ /**
+ * The maximum number of initialization status for some application specific failed reasons.
+ *
+ * @hide
+ */
+ public static final int MAXIMUM_NUMBER_OF_INITIALIZATION_STATUS_CUSTOM_ERROR = 2;
/**
* Indicates that the updated status is successful.
@@ -94,16 +91,6 @@
public static final int INITIALIZATION_STATUS_SUCCESS = 0;
/**
- * Indicates that the updated status is failure for some application specific reasons.
- */
- public static final int INITIALIZATION_STATUS_CUSTOM_ERROR_1 = 1;
-
- /**
- * Indicates that the updated status is failure for some application specific reasons.
- */
- public static final int INITIALIZATION_STATUS_CUSTOM_ERROR_2 = 2;
-
- /**
* Indicates that the callback wasn’t invoked within the timeout.
* This is used by system.
*/
@@ -229,6 +216,19 @@
}
/**
+ * Returns the maximum number of initialization status for some application specific failed
+ * reasons.
+ *
+ * Note: The value 0 is reserved for success.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static int getMaxCustomInitializationStatus() {
+ return MAXIMUM_NUMBER_OF_INITIALIZATION_STATUS_CUSTOM_ERROR;
+ }
+
+ /**
* Called when the device hardware (such as a DSP) detected the hotword, to request second stage
* validation before handing over the audio to the {@link AlwaysOnHotwordDetector}.
* <p>
@@ -298,9 +298,10 @@
* such data to the trusted process.
* @param callbackTimeoutMillis Timeout in milliseconds for the operation to invoke the
* statusCallback.
- * @param statusCallback Use this to return the updated result. This is non-null only when the
- * {@link HotwordDetectionService} is being initialized; and it is null if the state is updated
- * after that.
+ * @param statusCallback Use this to return the updated result; the allowed values are
+ * {@link #INITIALIZATION_STATUS_SUCCESS}, 1<->{@link #getMaxCustomInitializationStatus()}.
+ * This is non-null only when the {@link HotwordDetectionService} is being initialized; and it
+ * is null if the state is updated after that.
*
* @hide
*/
@@ -309,7 +310,7 @@
@Nullable PersistableBundle options,
@Nullable SharedMemory sharedMemory,
@DurationMillisLong long callbackTimeoutMillis,
- @Nullable @InitializationStatus IntConsumer statusCallback) {
+ @Nullable IntConsumer statusCallback) {
// TODO: Handle the unimplemented case by throwing?
}
@@ -389,6 +390,10 @@
if (callback != null) {
intConsumer =
value -> {
+ if (value > getMaxCustomInitializationStatus()) {
+ throw new IllegalArgumentException(
+ "The initialization status is invalid for " + value);
+ }
try {
Bundle status = new Bundle();
status.putInt(KEY_INITIALIZATION_STATUS, value);
diff --git a/core/java/android/service/voice/HotwordDetector.java b/core/java/android/service/voice/HotwordDetector.java
index d3c10ea..b2f810a 100644
--- a/core/java/android/service/voice/HotwordDetector.java
+++ b/core/java/android/service/voice/HotwordDetector.java
@@ -28,7 +28,6 @@
import android.os.ParcelFileDescriptor;
import android.os.PersistableBundle;
import android.os.SharedMemory;
-import android.service.voice.HotwordDetectionService.InitializationStatus;
/**
* Basic functionality for hotword detectors.
@@ -166,9 +165,12 @@
* Called when the {@link HotwordDetectionService} is created by the system and given a
* short amount of time to report it's initialization state.
*
- * @param status Info about initialization state of {@link HotwordDetectionService}.
+ * @param status Info about initialization state of {@link HotwordDetectionService}; the
+ * allowed values are {@link HotwordDetectionService#INITIALIZATION_STATUS_SUCCESS},
+ * 1<->{@link HotwordDetectionService#getMaxCustomInitializationStatus()},
+ * {@link HotwordDetectionService#INITIALIZATION_STATUS_UNKNOWN}.
*/
- void onHotwordDetectionServiceInitialized(@InitializationStatus int status);
+ void onHotwordDetectionServiceInitialized(int status);
/**
* Called with the {@link HotwordDetectionService} is restarted.
diff --git a/core/java/android/service/voice/VoiceInteractionManagerInternal.java b/core/java/android/service/voice/VoiceInteractionManagerInternal.java
index b38067b..f5c9591 100644
--- a/core/java/android/service/voice/VoiceInteractionManagerInternal.java
+++ b/core/java/android/service/voice/VoiceInteractionManagerInternal.java
@@ -41,4 +41,9 @@
public abstract boolean supportsLocalVoiceInteraction();
public abstract void stopLocalVoiceInteraction(IBinder callingActivity);
+
+ /**
+ * Returns whether the given package is currently in an active session
+ */
+ public abstract boolean hasActiveSession(String packageName);
}
\ No newline at end of file
diff --git a/core/java/android/speech/SpeechRecognizer.java b/core/java/android/speech/SpeechRecognizer.java
index b992007..37a97ca 100644
--- a/core/java/android/speech/SpeechRecognizer.java
+++ b/core/java/android/speech/SpeechRecognizer.java
@@ -40,6 +40,8 @@
import android.util.Log;
import android.util.Slog;
+import com.android.internal.R;
+
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -238,7 +240,7 @@
* @param context with which {@code SpeechRecognizer} will be created
* @return {@code true} if recognition is available, {@code false} otherwise
*/
- public static boolean isRecognitionAvailable(final Context context) {
+ public static boolean isRecognitionAvailable(@NonNull final Context context) {
// TODO(b/176578753): make sure this works well with system speech recognizers.
final List<ResolveInfo> list = context.getPackageManager().queryIntentServices(
new Intent(RecognitionService.SERVICE_INTERFACE), 0);
@@ -246,6 +248,38 @@
}
/**
+ * Checks whether an on-device speech recognition service is available on the system. If this
+ * method returns {@code false},
+ * {@link SpeechRecognizer#createOnDeviceSpeechRecognizer(Context)} will
+ * fail.
+ *
+ * @param context with which on-device {@code SpeechRecognizer} will be created
+ * @return {@code true} if on-device recognition is available, {@code false} otherwise
+ */
+ public static boolean isOnDeviceRecognitionAvailable(@NonNull final Context context) {
+ ComponentName componentName =
+ ComponentName.unflattenFromString(
+ context.getString(R.string.config_defaultOnDeviceSpeechRecognitionService));
+ if (componentName == null) {
+ return false;
+ }
+
+ List<ResolveInfo> resolveInfos =
+ context.getPackageManager().queryIntentServices(
+ new Intent(RecognitionService.SERVICE_INTERFACE), 0);
+ if (resolveInfos == null) {
+ return false;
+ }
+
+ for (ResolveInfo ri : resolveInfos) {
+ if (ri.serviceInfo != null && componentName.equals(ri.serviceInfo.getComponentName())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
* Factory method to create a new {@code SpeechRecognizer}. Please note that
* {@link #setRecognitionListener(RecognitionListener)} should be called before dispatching any
* command to the created {@code SpeechRecognizer}, otherwise no notifications will be
@@ -315,6 +349,8 @@
* notifications will be received.
*
* @param context in which to create {@code SpeechRecognizer}
+ * @throws UnsupportedOperationException iff {@link #isOnDeviceRecognitionAvailable(Context)}
+ * is false
* @return a new on-device {@code SpeechRecognizer}.
*/
@NonNull
@@ -324,6 +360,9 @@
throw new IllegalArgumentException("Context cannot be null");
}
checkIsCalledFromMainThread();
+ if (!isOnDeviceRecognitionAvailable(context)) {
+ throw new UnsupportedOperationException("On-device recognition is not available");
+ }
return new SpeechRecognizer(context, /* onDevice */ true);
}
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index 572e50a..c9a7949 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -72,7 +72,7 @@
DEFAULT_FLAGS.put("settings_contextual_home", "false");
DEFAULT_FLAGS.put(SETTINGS_PROVIDER_MODEL, "true");
DEFAULT_FLAGS.put(SETTINGS_USE_NEW_BACKUP_ELIGIBILITY_RULES, "true");
- DEFAULT_FLAGS.put(SETTINGS_ENABLE_SECURITY_HUB, "false");
+ DEFAULT_FLAGS.put(SETTINGS_ENABLE_SECURITY_HUB, "true");
}
private static final Set<String> PERSISTENT_FLAGS;
diff --git a/core/java/android/view/IRecentsAnimationController.aidl b/core/java/android/view/IRecentsAnimationController.aidl
index 7125232..6a2b723 100644
--- a/core/java/android/view/IRecentsAnimationController.aidl
+++ b/core/java/android/view/IRecentsAnimationController.aidl
@@ -18,6 +18,7 @@
import android.app.ActivityManager;
import android.view.IRemoteAnimationFinishedCallback;
+import android.view.SurfaceControl;
import android.graphics.GraphicBuffer;
import android.window.PictureInPictureSurfaceTransaction;
import android.window.TaskSnapshot;
@@ -43,9 +44,10 @@
* updated accordingly. This should be called before `finish`
* @param taskId for which the leash should be updated
* @param finishTransaction leash operations for the final transform.
+ * @param overlay the surface control for an overlay being shown above the pip (can be null)
*/
void setFinishTaskTransaction(int taskId,
- in PictureInPictureSurfaceTransaction finishTransaction);
+ in PictureInPictureSurfaceTransaction finishTransaction, in SurfaceControl overlay);
/**
* Notifies to the system that the animation into Recents should end, and all leashes associated
diff --git a/core/java/android/view/InsetsAnimationControlImpl.java b/core/java/android/view/InsetsAnimationControlImpl.java
index a67ec10..3255dd6 100644
--- a/core/java/android/view/InsetsAnimationControlImpl.java
+++ b/core/java/android/view/InsetsAnimationControlImpl.java
@@ -86,6 +86,7 @@
private final InsetsState mInitialInsetsState;
private final @AnimationType int mAnimationType;
private final @InsetsType int mTypes;
+ private @InsetsType int mControllingTypes;
private final InsetsAnimationControlCallbacks mController;
private final WindowInsetsAnimation mAnimation;
/** @see WindowInsetsAnimationController#hasZeroInsetsIme */
@@ -112,6 +113,7 @@
mControls = controls;
mListener = listener;
mTypes = types;
+ mControllingTypes = types;
mController = controller;
mInitialInsetsState = new InsetsState(state, true /* copySources */);
if (frame != null) {
@@ -187,6 +189,16 @@
}
@Override
+ public int getControllingTypes() {
+ return mControllingTypes;
+ }
+
+ @Override
+ public void notifyControlRevoked(@InsetsType int types) {
+ mControllingTypes &= ~types;
+ }
+
+ @Override
public @AnimationType int getAnimationType() {
return mAnimationType;
}
diff --git a/core/java/android/view/InsetsAnimationControlRunner.java b/core/java/android/view/InsetsAnimationControlRunner.java
index 0275b52..7787af5 100644
--- a/core/java/android/view/InsetsAnimationControlRunner.java
+++ b/core/java/android/view/InsetsAnimationControlRunner.java
@@ -29,11 +29,22 @@
public interface InsetsAnimationControlRunner {
/**
- * @return The {@link InsetsType} the animation of this runner is controlling.
+ * @return The {@link InsetsType} the animation of this runner controls.
*/
@InsetsType int getTypes();
/**
+ * @return The {@link InsetsType} the animation of this runner is controlling. This can be
+ * changed if a control is revoked.
+ */
+ @InsetsType int getControllingTypes();
+
+ /**
+ * Notifies {@link InsetsType types} of control are getting revoked.
+ */
+ void notifyControlRevoked(@InsetsType int types);
+
+ /**
* Cancels the animation.
*/
void cancel();
diff --git a/core/java/android/view/InsetsAnimationThreadControlRunner.java b/core/java/android/view/InsetsAnimationThreadControlRunner.java
index 6122c90..436a17c 100644
--- a/core/java/android/view/InsetsAnimationThreadControlRunner.java
+++ b/core/java/android/view/InsetsAnimationThreadControlRunner.java
@@ -141,6 +141,17 @@
@Override
@UiThread
+ public int getControllingTypes() {
+ return mControl.getControllingTypes();
+ }
+
+ @Override
+ public void notifyControlRevoked(@InsetsType int types) {
+ mControl.notifyControlRevoked(types);
+ }
+
+ @Override
+ @UiThread
public void cancel() {
InsetsAnimationThread.getHandler().post(mControl::cancel);
}
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index def9ca4..de7cc18 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -1224,9 +1224,11 @@
}
void notifyControlRevoked(InsetsSourceConsumer consumer) {
+ final @InsetsType int types = toPublicType(consumer.getType());
for (int i = mRunningAnimations.size() - 1; i >= 0; i--) {
InsetsAnimationControlRunner control = mRunningAnimations.get(i).runner;
- if ((control.getTypes() & toPublicType(consumer.getType())) != 0) {
+ control.notifyControlRevoked(types);
+ if (control.getControllingTypes() == 0) {
cancelAnimation(control, true /* invokeCallback */);
}
}
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 4647f47..679da31 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -3581,7 +3581,9 @@
}
structure.setChildCount(childrenCount);
- ArrayList<View> preorderedList = buildOrderedChildList();
+ ArrayList<View> tempPreorderedList = buildOrderedChildList();
+ ArrayList<View> preorderedList =
+ tempPreorderedList != null ? new ArrayList<>(tempPreorderedList) : null;
boolean customOrder = preorderedList == null
&& isChildrenDrawingOrderEnabled();
for (int i = 0; i < childrenCount; i++) {
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 4d1c666..9bbd5dd 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1201,8 +1201,7 @@
Looper.myLooper());
if (mAttachInfo.mThreadedRenderer != null) {
- InputMetricsListener listener =
- new InputMetricsListener(mInputEventReceiver);
+ InputMetricsListener listener = new InputMetricsListener();
mHardwareRendererObserver = new HardwareRendererObserver(
listener, listener.data, mHandler, true /*waitForPresentTime*/);
mAttachInfo.mThreadedRenderer.addObserver(mHardwareRendererObserver);
@@ -1356,6 +1355,11 @@
}
}
+ /**
+ * Register a callback to be executed when Webview overlay needs to merge a transaction.
+ * This callback will be executed on RenderThread worker thread, and released inside native code
+ * when CanvasContext is destroyed.
+ */
private void addASurfaceTransactionCallback() {
HardwareRenderer.ASurfaceTransactionCallback callback = (nativeTransactionObj,
nativeSurfaceControlObj,
@@ -1409,6 +1413,9 @@
if (mAttachInfo.mThreadedRenderer != null) {
mAttachInfo.mHardwareAccelerated =
mAttachInfo.mHardwareAccelerationRequested = true;
+ if (mHardwareRendererObserver != null) {
+ mAttachInfo.mThreadedRenderer.addObserver(mHardwareRendererObserver);
+ }
}
}
}
@@ -7500,7 +7507,8 @@
final View prevDragView = mCurrentDragView;
if (what == DragEvent.ACTION_DROP && event.mClipData != null) {
- event.mClipData.prepareToEnterProcess();
+ event.mClipData.prepareToEnterProcess(
+ mView.getContext().getAttributionSource());
}
// Now dispatch the drag/drop event
@@ -7710,6 +7718,7 @@
}
}
if (mAttachInfo.mThreadedRenderer != null) {
+ addASurfaceTransactionCallback();
mAttachInfo.mThreadedRenderer.setSurfaceControl(mSurfaceControl);
}
} else {
@@ -8111,6 +8120,9 @@
ThreadedRenderer hardwareRenderer = mAttachInfo.mThreadedRenderer;
if (hardwareRenderer != null) {
+ if (mHardwareRendererObserver != null) {
+ hardwareRenderer.removeObserver(mHardwareRendererObserver);
+ }
if (mView != null) {
hardwareRenderer.destroyHardwareResources(mView);
}
@@ -8612,18 +8624,12 @@
super.dispose();
}
}
- WindowInputEventReceiver mInputEventReceiver;
+ private WindowInputEventReceiver mInputEventReceiver;
final class InputMetricsListener
implements HardwareRendererObserver.OnFrameMetricsAvailableListener {
public long[] data = new long[FrameMetrics.Index.FRAME_STATS_COUNT];
- private InputEventReceiver mReceiver;
-
- InputMetricsListener(InputEventReceiver receiver) {
- mReceiver = receiver;
- }
-
@Override
public void onFrameMetricsAvailable(int dropCountSinceLastInvocation) {
final int inputEventId = (int) data[FrameMetrics.Index.INPUT_EVENT_ID];
@@ -8636,6 +8642,20 @@
// available, we cannot compute end-to-end input latency metrics.
return;
}
+ final long gpuCompletedTime = data[FrameMetrics.Index.GPU_COMPLETED];
+ if (mInputEventReceiver == null) {
+ return;
+ }
+ if (gpuCompletedTime >= presentTime) {
+ final double discrepancyMs = (gpuCompletedTime - presentTime) * 1E-6;
+ final long vsyncId = data[FrameMetrics.Index.FRAME_TIMELINE_VSYNC_ID];
+ Log.w(TAG, "Not reporting timeline because gpuCompletedTime is " + discrepancyMs
+ + "ms ahead of presentTime. FRAME_TIMELINE_VSYNC_ID=" + vsyncId
+ + ", INPUT_EVENT_ID=" + inputEventId);
+ // TODO(b/186664409): figure out why this sometimes happens
+ return;
+ }
+ mInputEventReceiver.reportTimeline(inputEventId, gpuCompletedTime, presentTime);
}
}
HardwareRendererObserver mHardwareRendererObserver;
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 5fb4e70..aa9ea19 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -1354,6 +1354,11 @@
public void setDecorFitsSystemWindows(boolean decorFitsSystemWindows) {
}
+ /** @hide */
+ public boolean decorFitsSystemWindows() {
+ return false;
+ }
+
/**
* Specify custom window attributes. <strong>PLEASE NOTE:</strong> the
* layout params you give here should generally be from values previously
@@ -1714,8 +1719,9 @@
* The window background drawable is drawn on top of the blurred region. The blur
* region bounds and rounded corners will mimic those of the background drawable.
* </p><p>
- * For the blur region to be visible, the window has to be translucent. See
- * {@link android.R.styleable#Window_windowIsTranslucent}.
+ * For the blur region to be visible, the window has to be translucent
+ * (see {@link android.R.attr#windowIsTranslucent}) and floating
+ * (see {@link android.R.attr#windowIsFloating}).
* </p><p>
* Note the difference with {@link WindowManager.LayoutParams#setBlurBehindRadius},
* which blurs the whole screen behind the window. Background blur blurs the screen behind
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index a169cb0..4df8fd2 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -25,7 +25,6 @@
import static android.view.autofill.Helper.toList;
import android.accessibilityservice.AccessibilityServiceInfo;
-import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -46,21 +45,16 @@
import android.content.pm.ResolveInfo;
import android.graphics.Rect;
import android.metrics.LogMaker;
-import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
-import android.os.CancellationSignal;
import android.os.Handler;
import android.os.IBinder;
-import android.os.ICancellationSignal;
import android.os.Looper;
import android.os.Parcelable;
import android.os.RemoteException;
import android.os.SystemClock;
import android.service.autofill.AutofillService;
-import android.service.autofill.FillCallback;
import android.service.autofill.FillEventHistory;
-import android.service.autofill.IFillCallback;
import android.service.autofill.UserData;
import android.text.TextUtils;
import android.util.ArrayMap;
@@ -80,7 +74,6 @@
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityNodeProvider;
import android.view.accessibility.AccessibilityWindowInfo;
-import android.view.inputmethod.InlineSuggestionsRequest;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.TextView;
@@ -106,7 +99,6 @@
import java.util.List;
import java.util.Objects;
import java.util.Set;
-import java.util.concurrent.Executor;
import sun.misc.Cleaner;
@@ -175,12 +167,6 @@
* shows an autofill save UI if the value of savable views have changed. If the user selects the
* option to Save, the current value of the views is then sent to the autofill service.
*
- * <p>There is another choice for the application to provide it's datasets to the Autofill framework
- * by setting an {@link AutofillRequestCallback} through
- * {@link #setAutofillRequestCallback(Executor, AutofillRequestCallback)}. The application can use
- * its callback instead of the default {@link AutofillService}. See
- * {@link AutofillRequestCallback} for more details.
- *
* <h3 id="additional-notes">Additional notes</h3>
*
* <p>It is safe to call <code>AutofillManager</code> methods from any thread.
@@ -306,7 +292,6 @@
/** @hide */ public static final int FLAG_ADD_CLIENT_DEBUG = 0x2;
/** @hide */ public static final int FLAG_ADD_CLIENT_VERBOSE = 0x4;
/** @hide */ public static final int FLAG_ADD_CLIENT_ENABLED_FOR_AUGMENTED_AUTOFILL_ONLY = 0x8;
- /** @hide */ public static final int FLAG_ENABLED_CLIENT_SUGGESTIONS = 0x20;
// NOTE: flag below is used by the session start receiver only, hence it can have values above
/** @hide */ public static final int RECEIVER_FLAG_SESSION_FOR_AUGMENTED_AUTOFILL_ONLY = 0x1;
@@ -607,11 +592,6 @@
@GuardedBy("mLock")
private boolean mEnabledForAugmentedAutofillOnly;
- @GuardedBy("mLock")
- @Nullable private AutofillRequestCallback mAutofillRequestCallback;
- @GuardedBy("mLock")
- @Nullable private Executor mRequestCallbackExecutor;
-
/** @hide */
public interface AutofillClient {
/**
@@ -1856,32 +1836,6 @@
return new AutofillId(parent.getAutofillViewId(), virtualId);
}
- /**
- * Sets the client's suggestions callback for autofill.
- *
- * @see AutofillRequestCallback
- *
- * @param executor specifies the thread upon which the callbacks will be invoked.
- * @param callback which handles autofill request to provide client's suggestions.
- */
- public void setAutofillRequestCallback(@NonNull @CallbackExecutor Executor executor,
- @NonNull AutofillRequestCallback callback) {
- synchronized (mLock) {
- mRequestCallbackExecutor = executor;
- mAutofillRequestCallback = callback;
- }
- }
-
- /**
- * clears the client's suggestions callback for autofill.
- */
- public void clearAutofillRequestCallback() {
- synchronized (mLock) {
- mRequestCallbackExecutor = null;
- mAutofillRequestCallback = null;
- }
- }
-
@GuardedBy("mLock")
private void startSessionLocked(@NonNull AutofillId id, @NonNull Rect bounds,
@NonNull AutofillValue value, int flags) {
@@ -1942,13 +1896,6 @@
}
}
- if (mAutofillRequestCallback != null) {
- if (sDebug) {
- Log.d(TAG, "startSession with the client suggestions provider");
- }
- flags |= FLAG_ENABLED_CLIENT_SUGGESTIONS;
- }
-
mService.startSession(client.autofillClientGetActivityToken(),
mServiceClient.asBinder(), id, bounds, value, mContext.getUserId(),
mCallback != null, flags, clientActivity,
@@ -2298,28 +2245,6 @@
}
}
- private void onFillRequest(InlineSuggestionsRequest request,
- CancellationSignal cancellationSignal, FillCallback callback) {
- final AutofillRequestCallback autofillRequestCallback;
- final Executor executor;
- synchronized (mLock) {
- autofillRequestCallback = mAutofillRequestCallback;
- executor = mRequestCallbackExecutor;
- }
- if (autofillRequestCallback != null && executor != null) {
- final long ident = Binder.clearCallingIdentity();
- try {
- executor.execute(() ->
- autofillRequestCallback.onFillRequest(
- request, cancellationSignal, callback));
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- } else {
- callback.onSuccess(null);
- }
- }
-
/** @hide */
public static final int SET_STATE_FLAG_ENABLED = 0x01;
/** @hide */
@@ -3699,23 +3624,6 @@
afm.post(() -> afm.requestShowSoftInput(id));
}
}
-
- @Override
- public void requestFillFromClient(int id, InlineSuggestionsRequest request,
- IFillCallback callback) {
- final AutofillManager afm = mAfm.get();
- if (afm != null) {
- ICancellationSignal transport = CancellationSignal.createTransport();
- try {
- callback.onCancellable(transport);
- } catch (RemoteException e) {
- Slog.w(TAG, "Error requesting a cancellation", e);
- }
-
- afm.onFillRequest(request, CancellationSignal.fromTransport(transport),
- new FillCallback(callback, id));
- }
- }
}
private static final class AugmentedAutofillManagerClient
diff --git a/core/java/android/view/autofill/AutofillRequestCallback.java b/core/java/android/view/autofill/AutofillRequestCallback.java
deleted file mode 100644
index e632a58..0000000
--- a/core/java/android/view/autofill/AutofillRequestCallback.java
+++ /dev/null
@@ -1,72 +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.
- */
-
-package android.view.autofill;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.os.CancellationSignal;
-import android.service.autofill.FillCallback;
-import android.view.inputmethod.InlineSuggestionsRequest;
-
-/**
- * <p>This class is used to provide some input suggestions to the Autofill framework.
- *
- * <P>When the user is requested to input something, Autofill will try to query input suggestions
- * for the user choosing. If the application want to provide some internal input suggestions,
- * implements this callback and register via
- * {@link AutofillManager#setAutofillRequestCallback(java.util.concurrent.Executor,
- * AutofillRequestCallback)}. Autofill will callback the
- * {@link #onFillRequest(InlineSuggestionsRequest, CancellationSignal, FillCallback)} to request
- * input suggestions.
- *
- * <P>To make sure the callback to take effect, must register before the autofill session starts.
- * If the autofill session is started, calls {@link AutofillManager#cancel()} to finish current
- * session, and then the callback will be used at the next restarted session.
- *
- * <P>To create a {@link android.service.autofill.FillResponse}, application should fetch
- * {@link AutofillId}s from its view structure. Below is an example:
- * <pre class="prettyprint">
- * AutofillId usernameId = findViewById(R.id.username).getAutofillId();
- * AutofillId passwordId = findViewById(R.id.password).getAutofillId();
- * </pre>
- * To learn more about creating a {@link android.service.autofill.FillResponse}, read
- * <a href="/guide/topics/text/autofill-services#fill">Fill out client views</a>.
- *
- * <P>To fallback to the default {@link android.service.autofill.AutofillService}, just respond
- * a null of the {@link android.service.autofill.FillResponse}. And then Autofill will do a fill
- * request with the default {@link android.service.autofill.AutofillService}. Or clear the callback
- * from {@link AutofillManager} via {@link AutofillManager#clearAutofillRequestCallback()}. If the
- * client would like to keep no suggestions for the field, respond with an empty
- * {@link android.service.autofill.FillResponse} which has no dataset.
- *
- * <P>IMPORTANT: This should not be used for displaying anything other than input suggestions, or
- * the keyboard may choose to block your app from the inline strip.
- */
-public interface AutofillRequestCallback {
- /**
- * Called by the Android system to decide if a screen can be autofilled by the callback.
- *
- * @param inlineSuggestionsRequest the {@link InlineSuggestionsRequest request} to handle if
- * currently inline suggestions are supported and can be displayed.
- * @param cancellationSignal signal for observing cancellation requests. The system will use
- * this to notify you that the fill result is no longer needed and you should stop
- * handling this fill request in order to save resources.
- * @param callback object used to notify the result of the request.
- */
- void onFillRequest(@Nullable InlineSuggestionsRequest inlineSuggestionsRequest,
- @NonNull CancellationSignal cancellationSignal, @NonNull FillCallback callback);
-}
diff --git a/core/java/android/view/autofill/IAutoFillManagerClient.aidl b/core/java/android/view/autofill/IAutoFillManagerClient.aidl
index 64507aa..1f833f6 100644
--- a/core/java/android/view/autofill/IAutoFillManagerClient.aidl
+++ b/core/java/android/view/autofill/IAutoFillManagerClient.aidl
@@ -24,11 +24,9 @@
import android.content.IntentSender;
import android.graphics.Rect;
import android.os.IBinder;
-import android.service.autofill.IFillCallback;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillValue;
import android.view.autofill.IAutofillWindowPresenter;
-import android.view.inputmethod.InlineSuggestionsRequest;
import android.view.KeyEvent;
import com.android.internal.os.IResultReceiver;
@@ -142,10 +140,4 @@
* Requests to show the soft input method if the focus is on the given id.
*/
void requestShowSoftInput(in AutofillId id);
-
- /**
- * Requests to determine if a screen can be autofilled by the client app.
- */
- void requestFillFromClient(int id, in InlineSuggestionsRequest request,
- in IFillCallback callback);
}
diff --git a/core/java/android/view/inputmethod/InlineSuggestionsRequest.java b/core/java/android/view/inputmethod/InlineSuggestionsRequest.java
index e1e1755..1eb1a93 100644
--- a/core/java/android/view/inputmethod/InlineSuggestionsRequest.java
+++ b/core/java/android/view/inputmethod/InlineSuggestionsRequest.java
@@ -111,22 +111,6 @@
private @Nullable InlinePresentationSpec mInlineTooltipPresentationSpec;
/**
- * Whether the IME supports inline suggestions from the default Autofill service that
- * provides the input view.
- *
- * Note: The default value is {@code true}.
- */
- private boolean mServiceSupported;
-
- /**
- * Whether the IME supports inline suggestions from the application that provides the
- * input view.
- *
- * Note: The default value is {@code true}.
- */
- private boolean mClientSupported;
-
- /**
* @hide
* @see {@link #mHostInputToken}.
*/
@@ -220,14 +204,6 @@
return Bundle.EMPTY;
}
- private static boolean defaultServiceSupported() {
- return true;
- }
-
- private static boolean defaultClientSupported() {
- return true;
- }
-
/** @hide */
abstract static class BaseBuilder {
abstract Builder setInlinePresentationSpecs(
@@ -240,25 +216,15 @@
abstract Builder setHostDisplayId(int value);
}
- /** @hide */
- public boolean isServiceSupported() {
- return mServiceSupported;
- }
-
- /** @hide */
- public boolean isClientSupported() {
- return mClientSupported;
- }
-
- // Code below generated by codegen v1.0.22.
+ // Code below generated by codegen v1.0.23.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
//
// To regenerate run:
- // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/view/inputmethod/InlineSuggestionsRequest.java
+ // $ codegen $ANDROID_BUILD_TOP/./frameworks/base/core/java/android/view/inputmethod/InlineSuggestionsRequest.java
//
// To exclude the generated code from IntelliJ auto-formatting enable (one-time):
// Settings > Editor > Code Style > Formatter Control
@@ -274,9 +240,7 @@
@NonNull Bundle extras,
@Nullable IBinder hostInputToken,
int hostDisplayId,
- @Nullable InlinePresentationSpec inlineTooltipPresentationSpec,
- boolean serviceSupported,
- boolean clientSupported) {
+ @Nullable InlinePresentationSpec inlineTooltipPresentationSpec) {
this.mMaxSuggestionCount = maxSuggestionCount;
this.mInlinePresentationSpecs = inlinePresentationSpecs;
com.android.internal.util.AnnotationValidations.validate(
@@ -293,8 +257,6 @@
this.mHostInputToken = hostInputToken;
this.mHostDisplayId = hostDisplayId;
this.mInlineTooltipPresentationSpec = inlineTooltipPresentationSpec;
- this.mServiceSupported = serviceSupported;
- this.mClientSupported = clientSupported;
onConstructed();
}
@@ -378,9 +340,7 @@
}
/**
- * The {@link InlinePresentationSpec} for the inline suggestion tooltip in the response.
- *
- * @see android.service.autofill.InlinePresentation#createTooltipPresentation(Slice, InlinePresentationSpec)
+ * Specifies the UI specification for the inline suggestion tooltip in the response.
*/
@DataClass.Generated.Member
public @Nullable InlinePresentationSpec getInlineTooltipPresentationSpec() {
@@ -401,9 +361,7 @@
"extras = " + mExtras + ", " +
"hostInputToken = " + mHostInputToken + ", " +
"hostDisplayId = " + mHostDisplayId + ", " +
- "inlineTooltipPresentationSpec = " + mInlineTooltipPresentationSpec + ", " +
- "serviceSupported = " + mServiceSupported + ", " +
- "clientSupported = " + mClientSupported +
+ "inlineTooltipPresentationSpec = " + mInlineTooltipPresentationSpec +
" }";
}
@@ -427,9 +385,7 @@
&& extrasEquals(that.mExtras)
&& java.util.Objects.equals(mHostInputToken, that.mHostInputToken)
&& mHostDisplayId == that.mHostDisplayId
- && java.util.Objects.equals(mInlineTooltipPresentationSpec, that.mInlineTooltipPresentationSpec)
- && mServiceSupported == that.mServiceSupported
- && mClientSupported == that.mClientSupported;
+ && java.util.Objects.equals(mInlineTooltipPresentationSpec, that.mInlineTooltipPresentationSpec);
}
@Override
@@ -447,8 +403,6 @@
_hash = 31 * _hash + java.util.Objects.hashCode(mHostInputToken);
_hash = 31 * _hash + mHostDisplayId;
_hash = 31 * _hash + java.util.Objects.hashCode(mInlineTooltipPresentationSpec);
- _hash = 31 * _hash + Boolean.hashCode(mServiceSupported);
- _hash = 31 * _hash + Boolean.hashCode(mClientSupported);
return _hash;
}
@@ -459,8 +413,6 @@
// void parcelFieldName(Parcel dest, int flags) { ... }
int flg = 0;
- if (mServiceSupported) flg |= 0x100;
- if (mClientSupported) flg |= 0x200;
if (mHostInputToken != null) flg |= 0x20;
if (mInlineTooltipPresentationSpec != null) flg |= 0x80;
dest.writeInt(flg);
@@ -486,8 +438,6 @@
// static FieldType unparcelFieldName(Parcel in) { ... }
int flg = in.readInt();
- boolean serviceSupported = (flg & 0x100) != 0;
- boolean clientSupported = (flg & 0x200) != 0;
int maxSuggestionCount = in.readInt();
List<InlinePresentationSpec> inlinePresentationSpecs = new ArrayList<>();
in.readParcelableList(inlinePresentationSpecs, InlinePresentationSpec.class.getClassLoader());
@@ -514,8 +464,6 @@
this.mHostInputToken = hostInputToken;
this.mHostDisplayId = hostDisplayId;
this.mInlineTooltipPresentationSpec = inlineTooltipPresentationSpec;
- this.mServiceSupported = serviceSupported;
- this.mClientSupported = clientSupported;
onConstructed();
}
@@ -549,8 +497,6 @@
private @Nullable IBinder mHostInputToken;
private int mHostDisplayId;
private @Nullable InlinePresentationSpec mInlineTooltipPresentationSpec;
- private boolean mServiceSupported;
- private boolean mClientSupported;
private long mBuilderFieldsSet = 0L;
@@ -683,9 +629,7 @@
}
/**
- * The {@link InlinePresentationSpec} for the inline suggestion tooltip in the response.
- *
- * @see android.service.autofill.InlinePresentation#createTooltipPresentation(Slice, InlinePresentationSpec)s
+ * Specifies the UI specification for the inline suggestion tooltip in the response.
*/
@DataClass.Generated.Member
public @NonNull Builder setInlineTooltipPresentationSpec(@NonNull InlinePresentationSpec value) {
@@ -695,38 +639,10 @@
return this;
}
- /**
- * Whether the IME supports inline suggestions from the default Autofill service that
- * provides the input view.
- *
- * Note: The default value is {@code true}.
- */
- @DataClass.Generated.Member
- public @NonNull Builder setServiceSupported(boolean value) {
- checkNotUsed();
- mBuilderFieldsSet |= 0x100;
- mServiceSupported = value;
- return this;
- }
-
- /**
- * Whether the IME supports inline suggestions from the application that provides the
- * input view.
- *
- * Note: The default value is {@code true}.
- */
- @DataClass.Generated.Member
- public @NonNull Builder setClientSupported(boolean value) {
- checkNotUsed();
- mBuilderFieldsSet |= 0x200;
- mClientSupported = value;
- return this;
- }
-
/** Builds the instance. This builder should not be touched after calling this! */
public @NonNull InlineSuggestionsRequest build() {
checkNotUsed();
- mBuilderFieldsSet |= 0x400; // Mark builder used
+ mBuilderFieldsSet |= 0x100; // Mark builder used
if ((mBuilderFieldsSet & 0x1) == 0) {
mMaxSuggestionCount = defaultMaxSuggestionCount();
@@ -749,12 +665,6 @@
if ((mBuilderFieldsSet & 0x80) == 0) {
mInlineTooltipPresentationSpec = defaultInlineTooltipPresentationSpec();
}
- if ((mBuilderFieldsSet & 0x100) == 0) {
- mServiceSupported = defaultServiceSupported();
- }
- if ((mBuilderFieldsSet & 0x200) == 0) {
- mClientSupported = defaultClientSupported();
- }
InlineSuggestionsRequest o = new InlineSuggestionsRequest(
mMaxSuggestionCount,
mInlinePresentationSpecs,
@@ -763,14 +673,12 @@
mExtras,
mHostInputToken,
mHostDisplayId,
- mInlineTooltipPresentationSpec,
- mServiceSupported,
- mClientSupported);
+ mInlineTooltipPresentationSpec);
return o;
}
private void checkNotUsed() {
- if ((mBuilderFieldsSet & 0x400) != 0) {
+ if ((mBuilderFieldsSet & 0x100) != 0) {
throw new IllegalStateException(
"This Builder should not be reused. Use a new Builder instance instead");
}
@@ -778,10 +686,10 @@
}
@DataClass.Generated(
- time = 1615798784918L,
- codegenVersion = "1.0.22",
+ time = 1621415989607L,
+ codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/view/inputmethod/InlineSuggestionsRequest.java",
- inputSignatures = "public static final int SUGGESTION_COUNT_UNLIMITED\nprivate final int mMaxSuggestionCount\nprivate final @android.annotation.NonNull java.util.List<android.widget.inline.InlinePresentationSpec> mInlinePresentationSpecs\nprivate @android.annotation.NonNull java.lang.String mHostPackageName\nprivate @android.annotation.NonNull android.os.LocaleList mSupportedLocales\nprivate @android.annotation.NonNull android.os.Bundle mExtras\nprivate @android.annotation.Nullable android.os.IBinder mHostInputToken\nprivate int mHostDisplayId\nprivate @android.annotation.Nullable android.widget.inline.InlinePresentationSpec mInlineTooltipPresentationSpec\nprivate boolean mServiceSupported\nprivate boolean mClientSupported\nprivate static final @android.compat.annotation.ChangeId @android.compat.annotation.EnabledSince long IME_AUTOFILL_DEFAULT_SUPPORTED_LOCALES_IS_EMPTY\npublic void setHostInputToken(android.os.IBinder)\nprivate boolean extrasEquals(android.os.Bundle)\nprivate void parcelHostInputToken(android.os.Parcel,int)\nprivate @android.annotation.Nullable android.os.IBinder unparcelHostInputToken(android.os.Parcel)\npublic void setHostDisplayId(int)\nprivate void onConstructed()\npublic void filterContentTypes()\nprivate static int defaultMaxSuggestionCount()\nprivate static java.lang.String defaultHostPackageName()\nprivate static android.widget.inline.InlinePresentationSpec defaultInlineTooltipPresentationSpec()\nprivate static android.os.LocaleList defaultSupportedLocales()\nprivate static @android.annotation.Nullable android.os.IBinder defaultHostInputToken()\nprivate static @android.annotation.Nullable int defaultHostDisplayId()\nprivate static @android.annotation.NonNull android.os.Bundle defaultExtras()\nprivate static boolean defaultServiceSupported()\nprivate static boolean defaultClientSupported()\npublic boolean isServiceSupported()\npublic boolean isClientSupported()\nclass InlineSuggestionsRequest extends java.lang.Object implements [android.os.Parcelable]\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setInlinePresentationSpecs(java.util.List<android.widget.inline.InlinePresentationSpec>)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostPackageName(java.lang.String)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostInputToken(android.os.IBinder)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostDisplayId(int)\nclass BaseBuilder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genBuilder=true)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setInlinePresentationSpecs(java.util.List<android.widget.inline.InlinePresentationSpec>)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostPackageName(java.lang.String)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostInputToken(android.os.IBinder)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostDisplayId(int)\nclass BaseBuilder extends java.lang.Object implements []")
+ inputSignatures = "public static final int SUGGESTION_COUNT_UNLIMITED\nprivate final int mMaxSuggestionCount\nprivate final @android.annotation.NonNull java.util.List<android.widget.inline.InlinePresentationSpec> mInlinePresentationSpecs\nprivate @android.annotation.NonNull java.lang.String mHostPackageName\nprivate @android.annotation.NonNull android.os.LocaleList mSupportedLocales\nprivate @android.annotation.NonNull android.os.Bundle mExtras\nprivate @android.annotation.Nullable android.os.IBinder mHostInputToken\nprivate int mHostDisplayId\nprivate @android.annotation.Nullable android.widget.inline.InlinePresentationSpec mInlineTooltipPresentationSpec\nprivate static final @android.compat.annotation.ChangeId @android.compat.annotation.EnabledSince long IME_AUTOFILL_DEFAULT_SUPPORTED_LOCALES_IS_EMPTY\npublic void setHostInputToken(android.os.IBinder)\nprivate boolean extrasEquals(android.os.Bundle)\nprivate void parcelHostInputToken(android.os.Parcel,int)\nprivate @android.annotation.Nullable android.os.IBinder unparcelHostInputToken(android.os.Parcel)\npublic void setHostDisplayId(int)\nprivate void onConstructed()\npublic void filterContentTypes()\nprivate static int defaultMaxSuggestionCount()\nprivate static java.lang.String defaultHostPackageName()\nprivate static android.widget.inline.InlinePresentationSpec defaultInlineTooltipPresentationSpec()\nprivate static android.os.LocaleList defaultSupportedLocales()\nprivate static @android.annotation.Nullable android.os.IBinder defaultHostInputToken()\nprivate static @android.annotation.Nullable int defaultHostDisplayId()\nprivate static @android.annotation.NonNull android.os.Bundle defaultExtras()\nclass InlineSuggestionsRequest extends java.lang.Object implements [android.os.Parcelable]\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setInlinePresentationSpecs(java.util.List<android.widget.inline.InlinePresentationSpec>)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostPackageName(java.lang.String)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostInputToken(android.os.IBinder)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostDisplayId(int)\nclass BaseBuilder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genBuilder=true)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setInlinePresentationSpecs(java.util.List<android.widget.inline.InlinePresentationSpec>)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostPackageName(java.lang.String)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostInputToken(android.os.IBinder)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostDisplayId(int)\nclass BaseBuilder extends java.lang.Object implements []")
@Deprecated
private void __metadata() {}
diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java
index c26b302..9b463bb 100644
--- a/core/java/android/view/inputmethod/InputMethodInfo.java
+++ b/core/java/android/view/inputmethod/InputMethodInfo.java
@@ -638,10 +638,11 @@
}
/**
- * Return {@code true} if this input method should be shown in the IME picker.
- * @hide
+ * Returns {@code true} if this input method should be shown in menus for selecting an Input
+ * Method, such as the system Input Method Picker. This is {@code false} if the IME is intended
+ * to be accessed programmatically.
*/
- public boolean showInInputMethodPicker() {
+ public boolean shouldShowInInputMethodPicker() {
return mShowInInputMethodPicker;
}
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 4298550..7eb8400 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -1519,17 +1519,25 @@
}
void setInputChannelLocked(InputChannel channel) {
- if (mCurChannel != channel) {
- if (mCurSender != null) {
- flushPendingEventsLocked();
- mCurSender.dispose();
- mCurSender = null;
- }
- if (mCurChannel != null) {
- mCurChannel.dispose();
- }
- mCurChannel = channel;
+ if (mCurChannel == channel) {
+ return;
}
+ if (mCurChannel != null && channel != null
+ && mCurChannel.getToken() == channel.getToken()) {
+ // channel is a dupe of 'mCurChannel', because they have the same token, and represent
+ // the same connection. Ignore the incoming channel and keep using 'mCurChannel' to
+ // avoid confusing the InputEventReceiver.
+ return;
+ }
+ if (mCurSender != null) {
+ flushPendingEventsLocked();
+ mCurSender.dispose();
+ mCurSender = null;
+ }
+ if (mCurChannel != null) {
+ mCurChannel.dispose();
+ }
+ mCurChannel = channel;
}
/**
diff --git a/core/java/android/view/translation/TranslationContext.java b/core/java/android/view/translation/TranslationContext.java
index 1d3d182..2a5dedd 100644
--- a/core/java/android/view/translation/TranslationContext.java
+++ b/core/java/android/view/translation/TranslationContext.java
@@ -37,9 +37,9 @@
*/
public static final @TranslationFlag int FLAG_TRANSLITERATION = 0x2;
/**
- * This context will enable the {@link Translator} to return dictionary results.
+ * This context will enable the {@link Translator} to return dictionary definitions.
*/
- public static final @TranslationFlag int FLAG_DICTIONARY_DESCRIPTION = 0x4;
+ public static final @TranslationFlag int FLAG_DEFINITIONS = 0x4;
/**
* {@link TranslationSpec} describing the source data to be translated.
@@ -69,7 +69,7 @@
- // Code below generated by codegen v1.0.22.
+ // Code below generated by codegen v1.0.23.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -86,7 +86,7 @@
@android.annotation.IntDef(flag = true, prefix = "FLAG_", value = {
FLAG_LOW_LATENCY,
FLAG_TRANSLITERATION,
- FLAG_DICTIONARY_DESCRIPTION
+ FLAG_DEFINITIONS
})
@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE)
@DataClass.Generated.Member
@@ -106,8 +106,8 @@
return "FLAG_LOW_LATENCY";
case FLAG_TRANSLITERATION:
return "FLAG_TRANSLITERATION";
- case FLAG_DICTIONARY_DESCRIPTION:
- return "FLAG_DICTIONARY_DESCRIPTION";
+ case FLAG_DEFINITIONS:
+ return "FLAG_DEFINITIONS";
default: return Integer.toHexString(value);
}
}
@@ -129,7 +129,7 @@
mTranslationFlags,
FLAG_LOW_LATENCY
| FLAG_TRANSLITERATION
- | FLAG_DICTIONARY_DESCRIPTION);
+ | FLAG_DEFINITIONS);
// onConstructed(); // You can define this method to get a callback
}
@@ -209,7 +209,7 @@
mTranslationFlags,
FLAG_LOW_LATENCY
| FLAG_TRANSLITERATION
- | FLAG_DICTIONARY_DESCRIPTION);
+ | FLAG_DEFINITIONS);
// onConstructed(); // You can define this method to get a callback
}
@@ -295,10 +295,10 @@
}
@DataClass.Generated(
- time = 1616199021789L,
- codegenVersion = "1.0.22",
+ time = 1621034221152L,
+ codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/view/translation/TranslationContext.java",
- inputSignatures = "public static final @android.view.translation.TranslationContext.TranslationFlag int FLAG_LOW_LATENCY\npublic static final @android.view.translation.TranslationContext.TranslationFlag int FLAG_TRANSLITERATION\npublic static final @android.view.translation.TranslationContext.TranslationFlag int FLAG_DICTIONARY_DESCRIPTION\nprivate final @android.annotation.NonNull android.view.translation.TranslationSpec mSourceSpec\nprivate final @android.annotation.NonNull android.view.translation.TranslationSpec mTargetSpec\nprivate final @android.view.translation.TranslationContext.TranslationFlag int mTranslationFlags\nprivate static int defaultTranslationFlags()\nclass TranslationContext extends java.lang.Object implements [android.os.Parcelable]\nclass BaseBuilder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genHiddenConstDefs=true, genToString=true, genBuilder=true)\nclass BaseBuilder extends java.lang.Object implements []")
+ inputSignatures = "public static final @android.view.translation.TranslationContext.TranslationFlag int FLAG_LOW_LATENCY\npublic static final @android.view.translation.TranslationContext.TranslationFlag int FLAG_TRANSLITERATION\npublic static final @android.view.translation.TranslationContext.TranslationFlag int FLAG_DEFINITIONS\nprivate final @android.annotation.NonNull android.view.translation.TranslationSpec mSourceSpec\nprivate final @android.annotation.NonNull android.view.translation.TranslationSpec mTargetSpec\nprivate final @android.view.translation.TranslationContext.TranslationFlag int mTranslationFlags\nprivate static int defaultTranslationFlags()\nclass TranslationContext extends java.lang.Object implements [android.os.Parcelable]\nclass BaseBuilder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genHiddenConstDefs=true, genToString=true, genBuilder=true)\nclass BaseBuilder extends java.lang.Object implements []")
@Deprecated
private void __metadata() {}
diff --git a/core/java/android/view/translation/TranslationRequest.java b/core/java/android/view/translation/TranslationRequest.java
index 1dc711b..7082e2b 100644
--- a/core/java/android/view/translation/TranslationRequest.java
+++ b/core/java/android/view/translation/TranslationRequest.java
@@ -98,9 +98,26 @@
return Collections.emptyList();
}
+ abstract static class BaseBuilder {
+ /**
+ * @deprecated use {@link Builder#setTranslationRequestValues(List)}.
+ */
+ @Deprecated
+ public abstract Builder addTranslationRequestValue(
+ @NonNull TranslationRequestValue value);
+
+ /**
+ * @deprecated use {@link Builder#setViewTranslationRequests(List)}.
+ */
+ @Deprecated
+ public abstract Builder addViewTranslationRequest(
+ @NonNull ViewTranslationRequest value);
+
+ }
- // Code below generated by codegen v1.0.22.
+
+ // Code below generated by codegen v1.0.23.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -275,7 +292,7 @@
*/
@SuppressWarnings("WeakerAccess")
@DataClass.Generated.Member
- public static final class Builder {
+ public static final class Builder extends BaseBuilder {
private @RequestFlags int mFlags;
private @NonNull List<TranslationRequestValue> mTranslationRequestValues;
@@ -312,6 +329,8 @@
/** @see #setTranslationRequestValues */
@DataClass.Generated.Member
+ @Override
+ @Deprecated
public @NonNull Builder addTranslationRequestValue(@NonNull TranslationRequestValue value) {
if (mTranslationRequestValues == null) setTranslationRequestValues(new ArrayList<>());
mTranslationRequestValues.add(value);
@@ -333,6 +352,8 @@
/** @see #setViewTranslationRequests */
@DataClass.Generated.Member
+ @Override
+ @Deprecated
public @NonNull Builder addViewTranslationRequest(@NonNull ViewTranslationRequest value) {
if (mViewTranslationRequests == null) setViewTranslationRequests(new ArrayList<>());
mViewTranslationRequests.add(value);
@@ -369,10 +390,10 @@
}
@DataClass.Generated(
- time = 1614132376448L,
- codegenVersion = "1.0.22",
+ time = 1620429997487L,
+ codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/view/translation/TranslationRequest.java",
- inputSignatures = "public static final @android.view.translation.TranslationRequest.RequestFlags int FLAG_TRANSLATION_RESULT\npublic static final @android.view.translation.TranslationRequest.RequestFlags int FLAG_DICTIONARY_RESULT\npublic static final @android.view.translation.TranslationRequest.RequestFlags int FLAG_TRANSLITERATION_RESULT\npublic static final @android.view.translation.TranslationRequest.RequestFlags int FLAG_PARTIAL_RESPONSES\nprivate final @android.view.translation.TranslationRequest.RequestFlags int mFlags\nprivate final @android.annotation.NonNull @com.android.internal.util.DataClass.PluralOf(\"translationRequestValue\") java.util.List<android.view.translation.TranslationRequestValue> mTranslationRequestValues\nprivate final @android.annotation.NonNull @com.android.internal.util.DataClass.PluralOf(\"viewTranslationRequest\") java.util.List<android.view.translation.ViewTranslationRequest> mViewTranslationRequests\nprivate static int defaultFlags()\nprivate static java.util.List<android.view.translation.TranslationRequestValue> defaultTranslationRequestValues()\nprivate static java.util.List<android.view.translation.ViewTranslationRequest> defaultViewTranslationRequests()\nclass TranslationRequest extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genHiddenConstDefs=true, genBuilder=true)")
+ inputSignatures = "public static final @android.view.translation.TranslationRequest.RequestFlags int FLAG_TRANSLATION_RESULT\npublic static final @android.view.translation.TranslationRequest.RequestFlags int FLAG_DICTIONARY_RESULT\npublic static final @android.view.translation.TranslationRequest.RequestFlags int FLAG_TRANSLITERATION_RESULT\npublic static final @android.view.translation.TranslationRequest.RequestFlags int FLAG_PARTIAL_RESPONSES\nprivate final @android.view.translation.TranslationRequest.RequestFlags int mFlags\nprivate final @android.annotation.NonNull @com.android.internal.util.DataClass.PluralOf(\"translationRequestValue\") java.util.List<android.view.translation.TranslationRequestValue> mTranslationRequestValues\nprivate final @android.annotation.NonNull @com.android.internal.util.DataClass.PluralOf(\"viewTranslationRequest\") java.util.List<android.view.translation.ViewTranslationRequest> mViewTranslationRequests\nprivate static int defaultFlags()\nprivate static java.util.List<android.view.translation.TranslationRequestValue> defaultTranslationRequestValues()\nprivate static java.util.List<android.view.translation.ViewTranslationRequest> defaultViewTranslationRequests()\nclass TranslationRequest extends java.lang.Object implements [android.os.Parcelable]\npublic abstract @java.lang.Deprecated android.view.translation.TranslationRequest.Builder addTranslationRequestValue(android.view.translation.TranslationRequestValue)\npublic abstract @java.lang.Deprecated android.view.translation.TranslationRequest.Builder addViewTranslationRequest(android.view.translation.ViewTranslationRequest)\nclass BaseBuilder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genToString=true, genHiddenConstDefs=true, genBuilder=true)\npublic abstract @java.lang.Deprecated android.view.translation.TranslationRequest.Builder addTranslationRequestValue(android.view.translation.TranslationRequestValue)\npublic abstract @java.lang.Deprecated android.view.translation.TranslationRequest.Builder addViewTranslationRequest(android.view.translation.ViewTranslationRequest)\nclass BaseBuilder extends java.lang.Object implements []")
@Deprecated
private void __metadata() {}
diff --git a/core/java/android/view/translation/TranslationRequestValue.java b/core/java/android/view/translation/TranslationRequestValue.java
index 0619618..5178cb1 100644
--- a/core/java/android/view/translation/TranslationRequestValue.java
+++ b/core/java/android/view/translation/TranslationRequestValue.java
@@ -46,22 +46,17 @@
}
/**
- * @return the text value as a {@link CharSequence}.
- *
- * @throws IllegalStateException if the format of this {@link TranslationRequestValue} is not a
- * text value.
+ * @return the text value as a {@link CharSequence} or {@code null} if the value is not of type
+ * text.
*/
- @NonNull
+ @Nullable
public CharSequence getText() {
- if (mText == null) {
- throw new IllegalStateException("Value is not of type text");
- }
return mText;
}
- // Code below generated by codegen v1.0.22.
+ // Code below generated by codegen v1.0.23.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -111,7 +106,7 @@
TranslationRequestValue that = (TranslationRequestValue) o;
//noinspection PointlessBooleanExpression
return true
- && java.util.Objects.equals(mText, that.mText);
+ && Objects.equals(mText, that.mText);
}
@Override
@@ -121,7 +116,7 @@
// int fieldNameHashCode() { ... }
int _hash = 1;
- _hash = 31 * _hash + java.util.Objects.hashCode(mText);
+ _hash = 31 * _hash + Objects.hashCode(mText);
return _hash;
}
@@ -171,10 +166,10 @@
};
@DataClass.Generated(
- time = 1613687761635L,
- codegenVersion = "1.0.22",
+ time = 1620259864154L,
+ codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/view/translation/TranslationRequestValue.java",
- inputSignatures = "private final @android.annotation.Nullable java.lang.CharSequence mText\npublic static @android.annotation.NonNull android.view.translation.TranslationRequestValue forText(java.lang.CharSequence)\npublic @android.annotation.NonNull java.lang.CharSequence getText()\nclass TranslationRequestValue extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genHiddenConstructor=true, genToString=true, genEqualsHashCode=true)")
+ inputSignatures = "private final @android.annotation.Nullable java.lang.CharSequence mText\npublic static @android.annotation.NonNull android.view.translation.TranslationRequestValue forText(java.lang.CharSequence)\npublic @android.annotation.Nullable java.lang.CharSequence getText()\nclass TranslationRequestValue extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genHiddenConstructor=true, genToString=true, genEqualsHashCode=true)")
@Deprecated
private void __metadata() {}
diff --git a/core/java/android/view/translation/TranslationResponseValue.java b/core/java/android/view/translation/TranslationResponseValue.java
index e8e9868..a68ae56 100644
--- a/core/java/android/view/translation/TranslationResponseValue.java
+++ b/core/java/android/view/translation/TranslationResponseValue.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -42,6 +43,17 @@
public static final int STATUS_ERROR = 1;
/**
+ * Name in the result of {@link #getExtras()} to pass dictionary definitions of the text
+ * categorized by parts of speech.
+ *
+ * <p>The dictionary definitions consists of groups of terms keyed by their corresponding parts
+ * of speech. This map-like structure is stored in a {@link Bundle}. The individual parts of
+ * speech can be traversed by {@link Bundle#keySet()} and used to get the corresponding list
+ * of terms as {@link CharSequence}s.</p>
+ */
+ public static final String EXTRA_DEFINITIONS = "android.view.translation.extra.DEFINITIONS";
+
+ /**
* The status code of this {@link TranslationResponseValue}.
*
* <p>If the status code is {@link #STATUS_ERROR}, no values are attached, and all getters will
@@ -56,11 +68,12 @@
private final CharSequence mText;
/**
- * The dictionary description of the translated text.
- * TODO: Describe the result structure.
+ * Extra results associated with the translated text.
+ *
+ * <p>The bundle includes {@link #EXTRA_DEFINITIONS}, obtained by {@link Bundle#getBundle}.</p>
*/
- @Nullable
- private final CharSequence mDictionaryDescription;
+ @NonNull
+ private final Bundle mExtras;
/**
* The transliteration result of the translated text.
@@ -74,15 +87,15 @@
*/
@NonNull
public static TranslationResponseValue forError() {
- return new TranslationResponseValue(STATUS_ERROR, null, null, null);
+ return new TranslationResponseValue(STATUS_ERROR, null, Bundle.EMPTY, null);
}
private static CharSequence defaultText() {
return null;
}
- private static CharSequence defaultDictionaryDescription() {
- return null;
+ private static Bundle defaultExtras() {
+ return Bundle.EMPTY;
}
private static CharSequence defaultTransliteration() {
@@ -96,7 +109,7 @@
- // Code below generated by codegen v1.0.22.
+ // Code below generated by codegen v1.0.23.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -134,7 +147,7 @@
/* package-private */ TranslationResponseValue(
@Status int statusCode,
@Nullable CharSequence text,
- @Nullable CharSequence dictionaryDescription,
+ @NonNull Bundle extras,
@Nullable CharSequence transliteration) {
this.mStatusCode = statusCode;
@@ -147,7 +160,9 @@
}
this.mText = text;
- this.mDictionaryDescription = dictionaryDescription;
+ this.mExtras = extras;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mExtras);
this.mTransliteration = transliteration;
// onConstructed(); // You can define this method to get a callback
@@ -173,12 +188,13 @@
}
/**
- * The dictionary description of the translated text.
- * TODO: Describe the result structure.
+ * Extra results associated with the translated text.
+ *
+ * <p>The bundle includes {@link #EXTRA_DEFINITIONS}, obtained by {@link Bundle#getBundle}.</p>
*/
@DataClass.Generated.Member
- public @Nullable CharSequence getDictionaryDescription() {
- return mDictionaryDescription;
+ public @NonNull Bundle getExtras() {
+ return mExtras;
}
/**
@@ -199,7 +215,7 @@
return "TranslationResponseValue { " +
"statusCode = " + statusToString(mStatusCode) + ", " +
"text = " + mText + ", " +
- "dictionaryDescription = " + mDictionaryDescription + ", " +
+ "extras = " + mExtras + ", " +
"transliteration = " + mTransliteration +
" }";
}
@@ -219,7 +235,7 @@
return true
&& mStatusCode == that.mStatusCode
&& Objects.equals(mText, that.mText)
- && Objects.equals(mDictionaryDescription, that.mDictionaryDescription)
+ && Objects.equals(mExtras, that.mExtras)
&& Objects.equals(mTransliteration, that.mTransliteration);
}
@@ -232,7 +248,7 @@
int _hash = 1;
_hash = 31 * _hash + mStatusCode;
_hash = 31 * _hash + Objects.hashCode(mText);
- _hash = 31 * _hash + Objects.hashCode(mDictionaryDescription);
+ _hash = 31 * _hash + Objects.hashCode(mExtras);
_hash = 31 * _hash + Objects.hashCode(mTransliteration);
return _hash;
}
@@ -245,12 +261,11 @@
byte flg = 0;
if (mText != null) flg |= 0x2;
- if (mDictionaryDescription != null) flg |= 0x4;
if (mTransliteration != null) flg |= 0x8;
dest.writeByte(flg);
dest.writeInt(mStatusCode);
if (mText != null) dest.writeCharSequence(mText);
- if (mDictionaryDescription != null) dest.writeCharSequence(mDictionaryDescription);
+ dest.writeBundle(mExtras);
if (mTransliteration != null) dest.writeCharSequence(mTransliteration);
}
@@ -268,7 +283,7 @@
byte flg = in.readByte();
int statusCode = in.readInt();
CharSequence text = (flg & 0x2) == 0 ? null : (CharSequence) in.readCharSequence();
- CharSequence dictionaryDescription = (flg & 0x4) == 0 ? null : (CharSequence) in.readCharSequence();
+ Bundle extras = in.readBundle();
CharSequence transliteration = (flg & 0x8) == 0 ? null : (CharSequence) in.readCharSequence();
this.mStatusCode = statusCode;
@@ -282,7 +297,9 @@
}
this.mText = text;
- this.mDictionaryDescription = dictionaryDescription;
+ this.mExtras = extras;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mExtras);
this.mTransliteration = transliteration;
// onConstructed(); // You can define this method to get a callback
@@ -311,7 +328,7 @@
private @Status int mStatusCode;
private @Nullable CharSequence mText;
- private @Nullable CharSequence mDictionaryDescription;
+ private @NonNull Bundle mExtras;
private @Nullable CharSequence mTransliteration;
private long mBuilderFieldsSet = 0L;
@@ -351,14 +368,15 @@
}
/**
- * The dictionary description of the translated text.
- * TODO: Describe the result structure.
+ * Extra results associated with the translated text.
+ *
+ * <p>The bundle includes {@link #EXTRA_DEFINITIONS}, obtained by {@link Bundle#getBundle}.</p>
*/
@DataClass.Generated.Member
- public @NonNull Builder setDictionaryDescription(@NonNull CharSequence value) {
+ public @NonNull Builder setExtras(@NonNull Bundle value) {
checkNotUsed();
mBuilderFieldsSet |= 0x4;
- mDictionaryDescription = value;
+ mExtras = value;
return this;
}
@@ -383,7 +401,7 @@
mText = defaultText();
}
if ((mBuilderFieldsSet & 0x4) == 0) {
- mDictionaryDescription = defaultDictionaryDescription();
+ mExtras = defaultExtras();
}
if ((mBuilderFieldsSet & 0x8) == 0) {
mTransliteration = defaultTransliteration();
@@ -391,7 +409,7 @@
TranslationResponseValue o = new TranslationResponseValue(
mStatusCode,
mText,
- mDictionaryDescription,
+ mExtras,
mTransliteration);
return o;
}
@@ -405,10 +423,10 @@
}
@DataClass.Generated(
- time = 1614983829716L,
- codegenVersion = "1.0.22",
+ time = 1621034223313L,
+ codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/view/translation/TranslationResponseValue.java",
- inputSignatures = "public static final int STATUS_SUCCESS\npublic static final int STATUS_ERROR\nprivate final @android.view.translation.TranslationResponseValue.Status int mStatusCode\nprivate final @android.annotation.Nullable java.lang.CharSequence mText\nprivate final @android.annotation.Nullable java.lang.CharSequence mDictionaryDescription\nprivate final @android.annotation.Nullable java.lang.CharSequence mTransliteration\npublic static @android.annotation.NonNull android.view.translation.TranslationResponseValue forError()\nprivate static java.lang.CharSequence defaultText()\nprivate static java.lang.CharSequence defaultDictionaryDescription()\nprivate static java.lang.CharSequence defaultTransliteration()\nclass TranslationResponseValue extends java.lang.Object implements [android.os.Parcelable]\nclass BaseBuilder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genBuilder=true, genToString=true, genEqualsHashCode=true, genHiddenConstDefs=true)\nclass BaseBuilder extends java.lang.Object implements []")
+ inputSignatures = "public static final int STATUS_SUCCESS\npublic static final int STATUS_ERROR\npublic static final java.lang.String EXTRA_DEFINITIONS\nprivate final @android.view.translation.TranslationResponseValue.Status int mStatusCode\nprivate final @android.annotation.Nullable java.lang.CharSequence mText\nprivate final @android.annotation.NonNull android.os.Bundle mExtras\nprivate final @android.annotation.Nullable java.lang.CharSequence mTransliteration\npublic static @android.annotation.NonNull android.view.translation.TranslationResponseValue forError()\nprivate static java.lang.CharSequence defaultText()\nprivate static android.os.Bundle defaultExtras()\nprivate static java.lang.CharSequence defaultTransliteration()\nclass TranslationResponseValue extends java.lang.Object implements [android.os.Parcelable]\nclass BaseBuilder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genBuilder=true, genToString=true, genEqualsHashCode=true, genHiddenConstDefs=true)\nclass BaseBuilder extends java.lang.Object implements []")
@Deprecated
private void __metadata() {}
diff --git a/core/java/android/view/translation/UiTranslationController.java b/core/java/android/view/translation/UiTranslationController.java
index 9e350d9..f79c329 100644
--- a/core/java/android/view/translation/UiTranslationController.java
+++ b/core/java/android/view/translation/UiTranslationController.java
@@ -658,9 +658,7 @@
msg.append("text=").append(value.getText() == null
? "null"
: "string[" + value.getText().length() + "], ");
- msg.append("dict=").append(value.getDictionaryDescription() == null
- ? "null"
- : "string[" + value.getDictionaryDescription().length() + "], ");
+ //TODO: append dictionary results.
msg.append("transliteration=").append(value.getTransliteration() == null
? "null"
: "string[" + value.getTransliteration().length() + "]}, ");
diff --git a/core/java/android/view/translation/UiTranslationStateCallback.java b/core/java/android/view/translation/UiTranslationStateCallback.java
index 1bae0ef..9aa089d 100644
--- a/core/java/android/view/translation/UiTranslationStateCallback.java
+++ b/core/java/android/view/translation/UiTranslationStateCallback.java
@@ -31,7 +31,9 @@
* @deprecated use {@link #onStarted(ULocale, ULocale)} instead.
*/
@Deprecated
- void onStarted(@NonNull String sourceLocale, @NonNull String targetLocale);
+ default void onStarted(@NonNull String sourceLocale, @NonNull String targetLocale) {
+ // no-op
+ }
/**
* The system is requesting translation of the UI from {@code sourceLocale} to {@code
diff --git a/core/java/android/view/translation/ViewTranslationRequest.java b/core/java/android/view/translation/ViewTranslationRequest.java
index 00f6ef2..a41749a 100644
--- a/core/java/android/view/translation/ViewTranslationRequest.java
+++ b/core/java/android/view/translation/ViewTranslationRequest.java
@@ -36,7 +36,7 @@
* be used by {@link android.service.translation.TranslationService}.
*/
@DataClass(genBuilder = false, genToString = true, genEqualsHashCode = true, genGetters = false,
- genHiddenConstructor = true)
+ genHiddenConstructor = true, genHiddenConstDefs = true)
public final class ViewTranslationRequest implements Parcelable {
/**
@@ -46,6 +46,14 @@
public static final String ID_TEXT = "android:text";
/**
+ * Constant id for the default view content description to be translated. This is used by
+ * {@link Builder#setValue(String, TranslationRequestValue)}.
+ *
+ * @hide
+ */
+ public static final String ID_CONTENT_DESCRIPTION = "android:content_description";
+
+ /**
* The {@link AutofillId} of the view associated with this request.
*/
@NonNull
@@ -191,6 +199,15 @@
//@formatter:off
+ /** @hide */
+ @android.annotation.StringDef(prefix = "ID_", value = {
+ ID_TEXT,
+ ID_CONTENT_DESCRIPTION
+ })
+ @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE)
+ @DataClass.Generated.Member
+ public @interface Id {}
+
/**
* Creates a new ViewTranslationRequest.
*
@@ -303,10 +320,10 @@
};
@DataClass.Generated(
- time = 1620259482911L,
+ time = 1621230365943L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/view/translation/ViewTranslationRequest.java",
- inputSignatures = "public static final java.lang.String ID_TEXT\nprivate final @android.annotation.NonNull android.view.autofill.AutofillId mAutofillId\nprivate final @android.annotation.NonNull @com.android.internal.util.DataClass.PluralOf(\"translationRequestValue\") java.util.Map<java.lang.String,android.view.translation.TranslationRequestValue> mTranslationRequestValues\npublic @android.annotation.NonNull android.view.translation.TranslationRequestValue getValue(java.lang.String)\npublic @android.annotation.NonNull java.util.Set<java.lang.String> getKeys()\npublic @android.annotation.NonNull android.view.autofill.AutofillId getAutofillId()\nprivate static java.util.Map<java.lang.String,android.view.translation.TranslationRequestValue> defaultTranslationRequestValues()\nclass ViewTranslationRequest extends java.lang.Object implements [android.os.Parcelable]\nprivate @android.annotation.NonNull android.view.autofill.AutofillId mAutofillId\nprivate @android.annotation.NonNull java.util.Map<java.lang.String,android.view.translation.TranslationRequestValue> mTranslationRequestValues\nprivate long mBuilderFieldsSet\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.view.translation.ViewTranslationRequest.Builder setValue(java.lang.String,android.view.translation.TranslationRequestValue)\npublic @android.annotation.NonNull android.view.translation.ViewTranslationRequest build()\n android.view.translation.ViewTranslationRequest.Builder setTranslationRequestValues(java.util.Map<java.lang.String,android.view.translation.TranslationRequestValue>)\nprivate void checkNotUsed()\nclass Builder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genBuilder=false, genToString=true, genEqualsHashCode=true, genGetters=false, genHiddenConstructor=true)")
+ inputSignatures = "public static final java.lang.String ID_TEXT\npublic static final java.lang.String ID_CONTENT_DESCRIPTION\nprivate final @android.annotation.NonNull android.view.autofill.AutofillId mAutofillId\nprivate final @android.annotation.NonNull @com.android.internal.util.DataClass.PluralOf(\"translationRequestValue\") java.util.Map<java.lang.String,android.view.translation.TranslationRequestValue> mTranslationRequestValues\npublic @android.annotation.NonNull android.view.translation.TranslationRequestValue getValue(java.lang.String)\npublic @android.annotation.NonNull java.util.Set<java.lang.String> getKeys()\npublic @android.annotation.NonNull android.view.autofill.AutofillId getAutofillId()\nprivate static java.util.Map<java.lang.String,android.view.translation.TranslationRequestValue> defaultTranslationRequestValues()\nclass ViewTranslationRequest extends java.lang.Object implements [android.os.Parcelable]\nprivate @android.annotation.NonNull android.view.autofill.AutofillId mAutofillId\nprivate @android.annotation.NonNull java.util.Map<java.lang.String,android.view.translation.TranslationRequestValue> mTranslationRequestValues\nprivate long mBuilderFieldsSet\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.view.translation.ViewTranslationRequest.Builder setValue(java.lang.String,android.view.translation.TranslationRequestValue)\npublic @android.annotation.NonNull android.view.translation.ViewTranslationRequest build()\n android.view.translation.ViewTranslationRequest.Builder setTranslationRequestValues(java.util.Map<java.lang.String,android.view.translation.TranslationRequestValue>)\nprivate void checkNotUsed()\nclass Builder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genBuilder=false, genToString=true, genEqualsHashCode=true, genGetters=false, genHiddenConstructor=true, genHiddenConstDefs=true)")
@Deprecated
private void __metadata() {}
diff --git a/core/java/android/webkit/WebViewDelegate.java b/core/java/android/webkit/WebViewDelegate.java
index ad123c1..1b9ff44 100644
--- a/core/java/android/webkit/WebViewDelegate.java
+++ b/core/java/android/webkit/WebViewDelegate.java
@@ -19,7 +19,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.UptimeMillisLong;
import android.app.ActivityThread;
import android.app.Application;
import android.app.ResourcesManager;
@@ -221,14 +220,12 @@
}
/**
- * Returns an array of startup timestamps. For the specification of array
- * see {@link WebViewFactory.Timestamp}.
+ * Get the timestamps at which various WebView startup events occurred in this process.
* This method must be called on the same thread where the
* WebViewChromiumFactoryProvider#create method was invoked.
*/
@NonNull
- @UptimeMillisLong
- public long[] getTimestamps() {
- return WebViewFactory.getTimestamps();
+ public WebViewFactory.StartupTimestamps getStartupTimestamps() {
+ return WebViewFactory.getStartupTimestamps();
}
}
diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java
index 9a38512..8d27cde 100644
--- a/core/java/android/webkit/WebViewFactory.java
+++ b/core/java/android/webkit/WebViewFactory.java
@@ -16,9 +16,9 @@
package android.webkit;
-import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
+import android.annotation.UptimeMillisLong;
import android.app.ActivityManager;
import android.app.AppGlobals;
import android.app.Application;
@@ -33,13 +33,12 @@
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.Trace;
+import android.os.UserHandle;
import android.util.AndroidRuntimeException;
import android.util.ArraySet;
import android.util.Log;
import java.io.File;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Method;
/**
@@ -72,44 +71,6 @@
private static boolean sWebViewDisabled;
private static String sDataDirectorySuffix; // stored here so it can be set without loading WV
- // Indices in sTimestamps array.
- /** @hide */
- @IntDef(value = {
- WEBVIEW_LOAD_START, CREATE_CONTEXT_START, CREATE_CONTEXT_END,
- ADD_ASSETS_START, ADD_ASSETS_END, GET_CLASS_LOADER_START, GET_CLASS_LOADER_END,
- NATIVE_LOAD_START, NATIVE_LOAD_END,
- PROVIDER_CLASS_FOR_NAME_START, PROVIDER_CLASS_FOR_NAME_END})
- @Retention(RetentionPolicy.SOURCE)
- public @interface Timestamp {
- }
-
- /** When the overall WebView provider load began. */
- public static final int WEBVIEW_LOAD_START = 0;
- /** Before creating the WebView APK Context. */
- public static final int CREATE_CONTEXT_START = 1;
- /** After creating the WebView APK Context. */
- public static final int CREATE_CONTEXT_END = 2;
- /** Before adding WebView assets to AssetManager. */
- public static final int ADD_ASSETS_START = 3;
- /** After adding WebView assets to AssetManager. */
- public static final int ADD_ASSETS_END = 4;
- /** Before creating the WebView ClassLoader. */
- public static final int GET_CLASS_LOADER_START = 5;
- /** After creating the WebView ClassLoader. */
- public static final int GET_CLASS_LOADER_END = 6;
- /** Before preloading the WebView native library. */
- public static final int NATIVE_LOAD_START = 7;
- /** After preloading the WebView native library. */
- public static final int NATIVE_LOAD_END = 8;
- /** Before looking up the WebView provider class. */
- public static final int PROVIDER_CLASS_FOR_NAME_START = 9;
- /** After looking up the WebView provider class. */
- public static final int PROVIDER_CLASS_FOR_NAME_END = 10;
- private static final int TIMESTAMPS_SIZE = 11;
-
- // WebView startup timestamps. To access elements use {@link Timestamp}.
- private static long[] sTimestamps = new long[TIMESTAMPS_SIZE];
-
// Error codes for loadWebViewNativeLibraryFromPackage
public static final int LIBLOAD_SUCCESS = 0;
public static final int LIBLOAD_WRONG_PACKAGE_NAME = 1;
@@ -130,6 +91,97 @@
// error for namespace lookup
public static final int LIBLOAD_FAILED_TO_FIND_NAMESPACE = 10;
+ /**
+ * Stores the timestamps at which various WebView startup events occurred in this process.
+ */
+ public static class StartupTimestamps {
+ long mWebViewLoadStart;
+ long mCreateContextStart;
+ long mCreateContextEnd;
+ long mAddAssetsStart;
+ long mAddAssetsEnd;
+ long mGetClassLoaderStart;
+ long mGetClassLoaderEnd;
+ long mNativeLoadStart;
+ long mNativeLoadEnd;
+ long mProviderClassForNameStart;
+ long mProviderClassForNameEnd;
+
+ StartupTimestamps() {}
+
+ /** When the overall WebView provider load began. */
+ @UptimeMillisLong
+ public long getWebViewLoadStart() {
+ return mWebViewLoadStart;
+ }
+
+ /** Before creating the WebView APK Context. */
+ @UptimeMillisLong
+ public long getCreateContextStart() {
+ return mCreateContextStart;
+ }
+
+ /** After creating the WebView APK Context. */
+ @UptimeMillisLong
+ public long getCreateContextEnd() {
+ return mCreateContextEnd;
+ }
+
+ /** Before adding WebView assets to AssetManager. */
+ @UptimeMillisLong
+ public long getAddAssetsStart() {
+ return mAddAssetsStart;
+ }
+
+ /** After adding WebView assets to AssetManager. */
+ @UptimeMillisLong
+ public long getAddAssetsEnd() {
+ return mAddAssetsEnd;
+ }
+
+ /** Before creating the WebView ClassLoader. */
+ @UptimeMillisLong
+ public long getGetClassLoaderStart() {
+ return mGetClassLoaderStart;
+ }
+
+ /** After creating the WebView ClassLoader. */
+ @UptimeMillisLong
+ public long getGetClassLoaderEnd() {
+ return mGetClassLoaderEnd;
+ }
+
+ /** Before preloading the WebView native library. */
+ @UptimeMillisLong
+ public long getNativeLoadStart() {
+ return mNativeLoadStart;
+ }
+
+ /** After preloading the WebView native library. */
+ @UptimeMillisLong
+ public long getNativeLoadEnd() {
+ return mNativeLoadEnd;
+ }
+
+ /** Before looking up the WebView provider class. */
+ @UptimeMillisLong
+ public long getProviderClassForNameStart() {
+ return mProviderClassForNameStart;
+ }
+
+ /** After looking up the WebView provider class. */
+ @UptimeMillisLong
+ public long getProviderClassForNameEnd() {
+ return mProviderClassForNameEnd;
+ }
+ }
+
+ static final StartupTimestamps sTimestamps = new StartupTimestamps();
+
+ @NonNull
+ static StartupTimestamps getStartupTimestamps() {
+ return sTimestamps;
+ }
private static String getWebViewPreparationErrorReason(int error) {
switch (error) {
@@ -273,7 +325,7 @@
// us honest and minimize usage of WebView internals when binding the proxy.
if (sProviderInstance != null) return sProviderInstance;
- sTimestamps[WEBVIEW_LOAD_START] = SystemClock.uptimeMillis();
+ sTimestamps.mWebViewLoadStart = SystemClock.uptimeMillis();
final int uid = android.os.Process.myUid();
if (uid == android.os.Process.ROOT_UID || uid == android.os.Process.SYSTEM_UID
|| uid == android.os.Process.PHONE_UID || uid == android.os.Process.NFC_UID
@@ -413,16 +465,19 @@
Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW,
"initialApplication.createApplicationContext");
- sTimestamps[CREATE_CONTEXT_START] = SystemClock.uptimeMillis();
+ sTimestamps.mCreateContextStart = SystemClock.uptimeMillis();
try {
// Construct an app context to load the Java code into the current app.
- Context webViewContext = initialApplication.createApplicationContext(
- ai,
- Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
+ Context webViewContext = initialApplication.createPackageContextAsUser(
+ ai.packageName,
+ Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY,
+ UserHandle.getUserHandleForUid(ai.uid),
+ PackageManager.MATCH_UNINSTALLED_PACKAGES
+ | PackageManager.MATCH_DEBUG_TRIAGED_MISSING);
sPackageInfo = newPackageInfo;
return webViewContext;
} finally {
- sTimestamps[CREATE_CONTEXT_END] = SystemClock.uptimeMillis();
+ sTimestamps.mCreateContextEnd = SystemClock.uptimeMillis();
Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
}
} catch (RemoteException | PackageManager.NameNotFoundException e) {
@@ -448,26 +503,26 @@
Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.getChromiumProviderClass()");
try {
- sTimestamps[ADD_ASSETS_START] = SystemClock.uptimeMillis();
+ sTimestamps.mAddAssetsStart = SystemClock.uptimeMillis();
for (String newAssetPath : webViewContext.getApplicationInfo().getAllApkPaths()) {
initialApplication.getAssets().addAssetPathAsSharedLibrary(newAssetPath);
}
- sTimestamps[ADD_ASSETS_END] = sTimestamps[GET_CLASS_LOADER_START] =
+ sTimestamps.mAddAssetsEnd = sTimestamps.mGetClassLoaderStart =
SystemClock.uptimeMillis();
ClassLoader clazzLoader = webViewContext.getClassLoader();
Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.loadNativeLibrary()");
- sTimestamps[GET_CLASS_LOADER_END] = sTimestamps[NATIVE_LOAD_START] =
+ sTimestamps.mGetClassLoaderEnd = sTimestamps.mNativeLoadStart =
SystemClock.uptimeMillis();
WebViewLibraryLoader.loadNativeLibrary(clazzLoader,
getWebViewLibrary(sPackageInfo.applicationInfo));
Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "Class.forName()");
- sTimestamps[NATIVE_LOAD_END] = sTimestamps[PROVIDER_CLASS_FOR_NAME_START] =
+ sTimestamps.mNativeLoadEnd = sTimestamps.mProviderClassForNameStart =
SystemClock.uptimeMillis();
try {
return getWebViewProviderClass(clazzLoader);
} finally {
- sTimestamps[PROVIDER_CLASS_FOR_NAME_END] = SystemClock.uptimeMillis();
+ sTimestamps.mProviderClassForNameEnd = SystemClock.uptimeMillis();
Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
}
} catch (ClassNotFoundException e) {
@@ -529,9 +584,4 @@
return IWebViewUpdateService.Stub.asInterface(
ServiceManager.getService(WEBVIEW_UPDATE_SERVICE_NAME));
}
-
- @NonNull
- static long[] getTimestamps() {
- return sTimestamps;
- }
}
diff --git a/core/java/android/widget/DatePickerCalendarDelegate.java b/core/java/android/widget/DatePickerCalendarDelegate.java
index 53e145e..ec07209 100755
--- a/core/java/android/widget/DatePickerCalendarDelegate.java
+++ b/core/java/android/widget/DatePickerCalendarDelegate.java
@@ -259,6 +259,11 @@
}
mCurrentDate.set(Calendar.YEAR, year);
+ if (mCurrentDate.compareTo(mMinDate) < 0) {
+ mCurrentDate.setTimeInMillis(mMinDate.getTimeInMillis());
+ } else if (mCurrentDate.compareTo(mMaxDate) > 0) {
+ mCurrentDate.setTimeInMillis(mMaxDate.getTimeInMillis());
+ }
onDateChanged(true, true);
// Automatically switch to day picker.
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index ee7818c..25c84ba 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -5827,8 +5827,9 @@
return context;
}
try {
- return context.createApplicationContext(mApplication,
- Context.CONTEXT_RESTRICTED);
+ return context.createPackageContextAsUser(mApplication.packageName,
+ Context.CONTEXT_RESTRICTED,
+ UserHandle.getUserHandleForUid(mApplication.uid));
} catch (NameNotFoundException e) {
Log.e(LOG_TAG, "Package name " + mApplication.packageName + " not found");
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 1a37b59..e0238b9 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -13924,6 +13924,10 @@
// TODO(b/176488462): apply the view's important for translation
requestBuilder.setValue(ViewTranslationRequest.ID_TEXT,
TranslationRequestValue.forText(mText));
+ if (!TextUtils.isEmpty(getContentDescription())) {
+ requestBuilder.setValue(ViewTranslationRequest.ID_CONTENT_DESCRIPTION,
+ TranslationRequestValue.forText(getContentDescription()));
+ }
}
requestsCollector.accept(requestBuilder.build());
}
diff --git a/core/java/android/widget/TextViewTranslationCallback.java b/core/java/android/widget/TextViewTranslationCallback.java
index 0376061..92c9142 100644
--- a/core/java/android/widget/TextViewTranslationCallback.java
+++ b/core/java/android/widget/TextViewTranslationCallback.java
@@ -19,11 +19,13 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Build;
+import android.text.TextUtils;
import android.text.method.TranslationTransformationMethod;
import android.util.Log;
import android.view.View;
import android.view.translation.UiTranslationManager;
import android.view.translation.ViewTranslationCallback;
+import android.view.translation.ViewTranslationRequest;
import android.view.translation.ViewTranslationResponse;
/**
@@ -46,6 +48,8 @@
private boolean mIsTextPaddingEnabled = false;
private CharSequence mPaddedText;
+ private CharSequence mContentDescription;
+
/**
* Invoked by the platform when receiving the successful {@link ViewTranslationResponse} for the
* view that provides the translatable information by {@link View#createTranslationRequest} and
@@ -86,6 +90,15 @@
}
if (mTranslationTransformation != null) {
((TextView) view).setTransformationMethod(mTranslationTransformation);
+ ViewTranslationResponse response = view.getViewTranslationResponse();
+ if (response.getKeys().contains(ViewTranslationRequest.ID_CONTENT_DESCRIPTION)) {
+ CharSequence translatedContentDescription =
+ response.getValue(ViewTranslationRequest.ID_CONTENT_DESCRIPTION).getText();
+ if (!TextUtils.isEmpty(translatedContentDescription)) {
+ mContentDescription = view.getContentDescription();
+ view.setContentDescription(translatedContentDescription);
+ }
+ }
} else {
if (DEBUG) {
// TODO(b/182433547): remove before S release
@@ -111,6 +124,9 @@
if (mTranslationTransformation != null) {
((TextView) view).setTransformationMethod(
mTranslationTransformation.getOriginalTransformationMethod());
+ if (!TextUtils.isEmpty(mContentDescription)) {
+ view.setContentDescription(mContentDescription);
+ }
} else {
if (DEBUG) {
// TODO(b/182433547): remove before S release
@@ -131,6 +147,7 @@
onHideTranslation(view);
clearTranslationTransformation();
mPaddedText = null;
+ mContentDescription = null;
} else {
if (DEBUG) {
// TODO(b/182433547): remove before S release
diff --git a/core/java/android/window/IWindowOrganizerController.aidl b/core/java/android/window/IWindowOrganizerController.aidl
index 0cd9b36..1223d72 100644
--- a/core/java/android/window/IWindowOrganizerController.aidl
+++ b/core/java/android/window/IWindowOrganizerController.aidl
@@ -78,17 +78,6 @@
IDisplayAreaOrganizerController getDisplayAreaOrganizerController();
/**
- * Take a screenshot of the requested Window token and place the content of the screenshot into
- * outSurfaceControl. The SurfaceControl will be a child of the token's parent, so it will be
- * a sibling of the token's window
- * @param token The token for the WindowContainer that should get a screenshot taken.
- * @param outSurfaceControl The SurfaceControl where the screenshot will be attached.
- *
- * @return true if the screenshot was successful, false otherwise.
- */
- boolean takeScreenshot(in WindowContainerToken token, out SurfaceControl outSurfaceControl);
-
- /**
* Registers a transition player with Core. There is only one of these at a time and calling
* this will replace the existing one if set.
*/
diff --git a/core/java/android/window/SplashScreenView.java b/core/java/android/window/SplashScreenView.java
index 8debe5d..d67fb32 100644
--- a/core/java/android/window/SplashScreenView.java
+++ b/core/java/android/window/SplashScreenView.java
@@ -17,6 +17,8 @@
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
+import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
+import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
import android.annotation.ColorInt;
import android.annotation.NonNull;
@@ -40,11 +42,13 @@
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
+import android.view.WindowInsetsController;
import android.view.WindowManager;
import android.widget.FrameLayout;
import com.android.internal.R;
import com.android.internal.policy.DecorView;
+import com.android.internal.util.ContrastColorUtil;
import java.time.Duration;
import java.time.Instant;
@@ -69,6 +73,12 @@
private static final String TAG = SplashScreenView.class.getSimpleName();
private static final boolean DEBUG = false;
+ private static final int LIGHT_BARS_MASK =
+ WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS
+ | WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
+ private static final int WINDOW_FLAG_MASK = FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
+ | FLAG_TRANSLUCENT_NAVIGATION | FLAG_TRANSLUCENT_STATUS;
+
private boolean mNotCopyable;
private boolean mRevealAnimationSupported = true;
private int mInitBackgroundColor;
@@ -84,10 +94,14 @@
private Activity mHostActivity;
// cache original window and status
private Window mWindow;
- private boolean mDrawBarBackground;
+ private int mAppWindowFlags;
private int mStatusBarColor;
private int mNavigationBarColor;
+ private int mSystemBarsAppearance;
private boolean mHasRemoved;
+ private boolean mNavigationContrastEnforced;
+ private boolean mStatusContrastEnforced;
+ private boolean mDecorFitsSystemWindows;
/**
* Internal builder to create a SplashScreenView object.
@@ -347,54 +361,63 @@
mWindow = null;
}
if (mHostActivity != null) {
- mHostActivity.detachSplashScreenView();
+ mHostActivity.setSplashScreenView(null);
+ mHostActivity = null;
}
mHasRemoved = true;
}
/**
- * Called when this view is attached to an activity.
+ * 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 attachHostActivity(Activity activity) {
+ public void attachHostActivityAndSetSystemUIColors(Activity activity, Window window) {
+ activity.setSplashScreenView(this);
mHostActivity = activity;
- }
-
- /**
- * Cache the root window.
- * @hide
- */
- public void cacheRootWindow(Window window) {
mWindow = window;
+ final WindowManager.LayoutParams attr = window.getAttributes();
+ mAppWindowFlags = attr.flags;
+ mStatusBarColor = window.getStatusBarColor();
+ mNavigationBarColor = window.getNavigationBarColor();
+ mSystemBarsAppearance = window.getInsetsController().getSystemBarsAppearance();
+ mNavigationContrastEnforced = window.isNavigationBarContrastEnforced();
+ mStatusContrastEnforced = window.isStatusBarContrastEnforced();
+ mDecorFitsSystemWindows = window.decorFitsSystemWindows();
+
+ applySystemBarsContrastColor(window.getInsetsController(), mInitBackgroundColor);
+ // Let app draw the background of bars.
+ window.addFlags(FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
+ // Use specified bar colors instead of window background.
+ window.clearFlags(FLAG_TRANSLUCENT_STATUS | FLAG_TRANSLUCENT_NAVIGATION);
+ window.setStatusBarColor(Color.TRANSPARENT);
+ window.setNavigationBarColor(Color.TRANSPARENT);
+ window.setDecorFitsSystemWindows(false);
+ window.setStatusBarContrastEnforced(false);
+ window.setNavigationBarContrastEnforced(false);
+ }
+
+ /** Called when this view is removed from the host activity. */
+ private void restoreSystemUIColors() {
+ mWindow.setFlags(mAppWindowFlags, WINDOW_FLAG_MASK);
+ mWindow.setStatusBarColor(mStatusBarColor);
+ mWindow.setNavigationBarColor(mNavigationBarColor);
+ mWindow.getInsetsController().setSystemBarsAppearance(mSystemBarsAppearance,
+ LIGHT_BARS_MASK);
+ mWindow.setDecorFitsSystemWindows(mDecorFitsSystemWindows);
+ mWindow.setStatusBarContrastEnforced(mStatusContrastEnforced);
+ mWindow.setNavigationBarContrastEnforced(mNavigationContrastEnforced);
}
/**
- * Called after SplashScreenView has added on the root window.
+ * Makes the icon color of system bars contrast.
* @hide
*/
- public void makeSystemUIColorsTransparent() {
- if (mWindow != null) {
- final WindowManager.LayoutParams attr = mWindow.getAttributes();
- mDrawBarBackground = (attr.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
- mWindow.addFlags(FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
- mStatusBarColor = mWindow.getStatusBarColor();
- mNavigationBarColor = mWindow.getNavigationBarDividerColor();
- mWindow.setStatusBarColor(Color.TRANSPARENT);
- mWindow.setNavigationBarColor(Color.TRANSPARENT);
- }
- setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
- | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
- | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
- }
-
- private void restoreSystemUIColors() {
- if (mWindow != null) {
- if (!mDrawBarBackground) {
- mWindow.clearFlags(FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
- }
- mWindow.setStatusBarColor(mStatusBarColor);
- mWindow.setNavigationBarColor(mNavigationBarColor);
- }
+ public static void applySystemBarsContrastColor(WindowInsetsController windowInsetsController,
+ int backgroundColor) {
+ final int lightBarAppearance = ContrastColorUtil.isColorLight(backgroundColor)
+ ? LIGHT_BARS_MASK : 0;
+ windowInsetsController.setSystemBarsAppearance(lightBarAppearance, LIGHT_BARS_MASK);
}
/**
diff --git a/core/java/android/window/WindowOrganizer.java b/core/java/android/window/WindowOrganizer.java
index bcd0e8d..544d422 100644
--- a/core/java/android/window/WindowOrganizer.java
+++ b/core/java/android/window/WindowOrganizer.java
@@ -25,7 +25,6 @@
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Singleton;
-import android.view.SurfaceControl;
/**
* Base class for organizing specific types of windows like Tasks and DisplayAreas
@@ -112,28 +111,6 @@
}
/**
- * Take a screenshot for a specified Window
- * @param token The token for the WindowContainer that should get a screenshot taken.
- * @return A SurfaceControl where the screenshot will be attached, or null if failed.
- *
- * @hide
- */
- @Nullable
- @RequiresPermission(android.Manifest.permission.READ_FRAME_BUFFER)
- public SurfaceControl takeScreenshot(@NonNull WindowContainerToken token) {
- try {
- SurfaceControl surfaceControl = new SurfaceControl();
- if (getWindowOrganizerController().takeScreenshot(token, surfaceControl)) {
- return surfaceControl;
- } else {
- return null;
- }
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
* Register an ITransitionPlayer to handle transition animations.
* @hide
*/
diff --git a/core/java/com/android/internal/app/procstats/OWNERS b/core/java/com/android/internal/app/procstats/OWNERS
new file mode 100644
index 0000000..72c0a9e
--- /dev/null
+++ b/core/java/com/android/internal/app/procstats/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/am/OWNERS
diff --git a/core/java/com/android/internal/graphics/fonts/IFontManager.aidl b/core/java/com/android/internal/graphics/fonts/IFontManager.aidl
index 1c7eca8..87df5eb 100644
--- a/core/java/com/android/internal/graphics/fonts/IFontManager.aidl
+++ b/core/java/com/android/internal/graphics/fonts/IFontManager.aidl
@@ -30,7 +30,5 @@
interface IFontManager {
FontConfig getFontConfig();
- int updateFontFile(in FontUpdateRequest request, int baseVersion);
-
int updateFontFamily(in List<FontUpdateRequest> request, int baseVersion);
}
diff --git a/core/java/com/android/internal/jank/InteractionJankMonitor.java b/core/java/com/android/internal/jank/InteractionJankMonitor.java
index 0441594..f029e6a 100644
--- a/core/java/com/android/internal/jank/InteractionJankMonitor.java
+++ b/core/java/com/android/internal/jank/InteractionJankMonitor.java
@@ -28,6 +28,7 @@
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_CLOSE_TO_PIP;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_LAUNCH_FROM_ICON;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_LAUNCH_FROM_RECENTS;
+import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_LAUNCH_FROM_WIDGET;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_OPEN_ALL_APPS;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_QUICK_SWITCH;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_PASSWORD_APPEAR;
@@ -144,6 +145,7 @@
public static final int CUJ_LOCKSCREEN_TRANSITION_TO_AOD = 24;
public static final int CUJ_LAUNCHER_OPEN_ALL_APPS = 25;
public static final int CUJ_LAUNCHER_ALL_APPS_SCROLL = 26;
+ public static final int CUJ_LAUNCHER_APP_LAUNCH_FROM_WIDGET = 27;
private static final int NO_STATSD_LOGGING = -1;
@@ -179,6 +181,7 @@
UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_TRANSITION_TO_AOD,
UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_OPEN_ALL_APPS,
UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_ALL_APPS_SCROLL,
+ UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_LAUNCH_FROM_WIDGET,
};
private static volatile InteractionJankMonitor sInstance;
@@ -225,6 +228,7 @@
CUJ_LOCKSCREEN_TRANSITION_TO_AOD,
CUJ_LAUNCHER_OPEN_ALL_APPS,
CUJ_LAUNCHER_ALL_APPS_SCROLL,
+ CUJ_LAUNCHER_APP_LAUNCH_FROM_WIDGET,
})
@Retention(RetentionPolicy.SOURCE)
public @interface CujType {
@@ -537,6 +541,8 @@
return "CUJ_LAUNCHER_OPEN_ALL_APPS";
case CUJ_LAUNCHER_ALL_APPS_SCROLL:
return "CUJ_LAUNCHER_ALL_APPS_SCROLL";
+ case CUJ_LAUNCHER_APP_LAUNCH_FROM_WIDGET:
+ return "LAUNCHER_APP_LAUNCH_FROM_WIDGET";
}
return "UNKNOWN";
}
diff --git a/core/java/com/android/internal/os/BatteryChargeCalculator.java b/core/java/com/android/internal/os/BatteryChargeCalculator.java
index 0690d1f..8178529 100644
--- a/core/java/com/android/internal/os/BatteryChargeCalculator.java
+++ b/core/java/com/android/internal/os/BatteryChargeCalculator.java
@@ -63,10 +63,15 @@
builder.setChargeTimeRemainingMs(chargeTimeRemainingMs / 1000);
}
+ long dischargeMah = batteryStats.getUahDischarge(BatteryStats.STATS_SINCE_CHARGED) / 1000;
+ if (dischargeMah == 0) {
+ dischargeMah = (long) ((dischargedPowerLowerBoundMah + dischargedPowerUpperBoundMah) / 2
+ + 0.5);
+ }
+
builder.getAggregateBatteryConsumerBuilder(
BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE)
- .setConsumedPower(
- (dischargedPowerLowerBoundMah + dischargedPowerUpperBoundMah) / 2);
+ .setConsumedPower(dischargeMah);
}
@Override
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 56f81e2..0938c85 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -610,18 +610,32 @@
}
public interface Clocks {
- public long elapsedRealtime();
- public long uptimeMillis();
+ /** Elapsed Realtime, see SystemClock.elapsedRealtime() */
+ long elapsedRealtime();
+
+ /** Uptime, see SystemClock.uptimeMillis() */
+ long uptimeMillis();
+
+ /** Wall-clock time as per System.currentTimeMillis() */
+ long currentTimeMillis();
}
public static class SystemClocks implements Clocks {
+
+ @Override
public long elapsedRealtime() {
return SystemClock.elapsedRealtime();
}
+ @Override
public long uptimeMillis() {
return SystemClock.uptimeMillis();
}
+
+ @Override
+ public long currentTimeMillis() {
+ return System.currentTimeMillis();
+ }
}
public interface ExternalStatsSync {
@@ -1163,7 +1177,7 @@
public BatteryStatsImpl(Clocks clocks) {
init(clocks);
- mStartClockTimeMs = System.currentTimeMillis();
+ mStartClockTimeMs = clocks.currentTimeMillis();
mStatsFile = null;
mCheckinFile = null;
mDailyFile = null;
@@ -3694,7 +3708,7 @@
if (dataSize == 0) {
// The history is currently empty; we need it to start with a time stamp.
- cur.currentTime = System.currentTimeMillis();
+ cur.currentTime = mClocks.currentTimeMillis();
addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_RESET, cur);
}
addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, cur);
@@ -3914,7 +3928,7 @@
}
public void noteCurrentTimeChangedLocked() {
- final long currentTime = System.currentTimeMillis();
+ final long currentTime = mClocks.currentTimeMillis();
final long elapsedRealtime = mClocks.elapsedRealtime();
final long uptime = mClocks.uptimeMillis();
noteCurrentTimeChangedLocked(currentTime, elapsedRealtime, uptime);
@@ -4237,7 +4251,7 @@
if (mPretendScreenOff != pretendScreenOff) {
mPretendScreenOff = pretendScreenOff;
noteScreenStateLocked(pretendScreenOff ? Display.STATE_OFF : Display.STATE_ON,
- mClocks.elapsedRealtime(), mClocks.uptimeMillis(), System.currentTimeMillis());
+ mClocks.elapsedRealtime(), mClocks.uptimeMillis(), mClocks.currentTimeMillis());
}
}
@@ -4827,7 +4841,7 @@
@GuardedBy("this")
public void noteScreenStateLocked(int state) {
noteScreenStateLocked(state, mClocks.elapsedRealtime(), mClocks.uptimeMillis(),
- System.currentTimeMillis());
+ mClocks.currentTimeMillis());
}
@GuardedBy("this")
@@ -5064,31 +5078,46 @@
}
public void notePowerSaveModeLocked(boolean enabled) {
- notePowerSaveModeLocked(enabled, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
+ notePowerSaveModeLocked(enabled, mClocks.elapsedRealtime(), mClocks.uptimeMillis(), false);
}
- public void notePowerSaveModeLocked(boolean enabled, long elapsedRealtimeMs, long uptimeMs) {
+ /**
+ * Handles power save mode state changes.
+ */
+ public void notePowerSaveModeLocked(boolean enabled, long elapsedRealtimeMs, long uptimeMs,
+ boolean forceLog) {
if (mPowerSaveModeEnabled != enabled) {
int stepState = enabled ? STEP_LEVEL_MODE_POWER_SAVE : 0;
- mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_POWER_SAVE) ^ stepState;
- mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_POWER_SAVE) | stepState;
+ mModStepMode |= (mCurStepMode & STEP_LEVEL_MODE_POWER_SAVE) ^ stepState;
+ mCurStepMode = (mCurStepMode & ~STEP_LEVEL_MODE_POWER_SAVE) | stepState;
mPowerSaveModeEnabled = enabled;
if (enabled) {
mHistoryCur.states2 |= HistoryItem.STATE2_POWER_SAVE_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Power save mode enabled to: "
- + Integer.toHexString(mHistoryCur.states2));
+ if (DEBUG_HISTORY) {
+ Slog.v(TAG, "Power save mode enabled to: "
+ + Integer.toHexString(mHistoryCur.states2));
+ }
mPowerSaveModeEnabledTimer.startRunningLocked(elapsedRealtimeMs);
} else {
mHistoryCur.states2 &= ~HistoryItem.STATE2_POWER_SAVE_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Power save mode disabled to: "
- + Integer.toHexString(mHistoryCur.states2));
+ if (DEBUG_HISTORY) {
+ Slog.v(TAG, "Power save mode disabled to: "
+ + Integer.toHexString(mHistoryCur.states2));
+ }
mPowerSaveModeEnabledTimer.stopRunningLocked(elapsedRealtimeMs);
}
addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
FrameworkStatsLog.write(FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED,
enabled
- ? FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED__STATE__ON
- : FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED__STATE__OFF);
+ ? FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED__STATE__ON
+ : FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED__STATE__OFF);
+ } else if (forceLog) {
+ // Log an initial value for BATTERY_SAVER_MODE_STATE_CHANGED in order to
+ // allow the atom to read all future state changes.
+ FrameworkStatsLog.write(FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED,
+ enabled
+ ? FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED__STATE__ON
+ : FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED__STATE__OFF);
}
}
@@ -6972,7 +7001,7 @@
}
@Override public long getStartClockTime() {
- final long currentTimeMs = System.currentTimeMillis();
+ final long currentTimeMs = mClocks.currentTimeMillis();
if ((currentTimeMs > MILLISECONDS_IN_YEAR
&& mStartClockTimeMs < (currentTimeMs - MILLISECONDS_IN_YEAR))
|| (mStartClockTimeMs > currentTimeMs)) {
@@ -10735,7 +10764,7 @@
public void updateDailyDeadlineLocked() {
// Get the current time.
- long currentTimeMs = mDailyStartTimeMs = System.currentTimeMillis();
+ long currentTimeMs = mDailyStartTimeMs = mClocks.currentTimeMillis();
Calendar calDeadline = Calendar.getInstance();
calDeadline.setTimeInMillis(currentTimeMs);
@@ -10763,7 +10792,7 @@
public void recordDailyStatsLocked() {
DailyItem item = new DailyItem();
item.mStartTime = mDailyStartTimeMs;
- item.mEndTime = System.currentTimeMillis();
+ item.mEndTime = mClocks.currentTimeMillis();
boolean hasData = false;
if (mDailyDischargeStepTracker.mNumStepDurations > 0) {
hasData = true;
@@ -11128,7 +11157,7 @@
}
void initTimes(long uptimeUs, long realtimeUs) {
- mStartClockTimeMs = System.currentTimeMillis();
+ mStartClockTimeMs = mClocks.currentTimeMillis();
mOnBatteryTimeBase.init(uptimeUs, realtimeUs);
mOnBatteryScreenOffTimeBase.init(uptimeUs, realtimeUs);
mRealtimeUs = 0;
@@ -13091,13 +13120,11 @@
if (Process.isIsolated(uid)) {
// This could happen if the isolated uid mapping was removed before that process
// was actually killed.
- mCpuUidUserSysTimeReader.removeUid(uid);
if (DEBUG) Slog.d(TAG, "Got readings for an isolated uid: " + uid);
return;
}
if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
if (DEBUG) Slog.d(TAG, "Got readings for an invalid user's uid " + uid);
- mCpuUidUserSysTimeReader.removeUid(uid);
return;
}
final Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, startTimeMs);
@@ -13202,19 +13229,16 @@
mWakeLockAllocationsUs = null;
final long startTimeMs = mClocks.uptimeMillis();
final long elapsedRealtimeMs = mClocks.elapsedRealtime();
- final List<Integer> uidsToRemove = new ArrayList<>();
// If power is being accumulated for attribution, data needs to be read immediately.
final boolean forceRead = powerAccumulator != null;
mCpuUidFreqTimeReader.readDelta(forceRead, (uid, cpuFreqTimeMs) -> {
uid = mapUid(uid);
if (Process.isIsolated(uid)) {
- uidsToRemove.add(uid);
if (DEBUG) Slog.d(TAG, "Got freq readings for an isolated uid: " + uid);
return;
}
if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
if (DEBUG) Slog.d(TAG, "Got freq readings for an invalid user's uid " + uid);
- uidsToRemove.add(uid);
return;
}
final Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, startTimeMs);
@@ -13278,9 +13302,6 @@
}
}
});
- for (int uid : uidsToRemove) {
- mCpuUidFreqTimeReader.removeUid(uid);
- }
final long elapsedTimeMs = mClocks.uptimeMillis() - startTimeMs;
if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
@@ -13332,25 +13353,19 @@
public void readKernelUidCpuActiveTimesLocked(boolean onBattery) {
final long startTimeMs = mClocks.uptimeMillis();
final long elapsedRealtimeMs = mClocks.elapsedRealtime();
- final List<Integer> uidsToRemove = new ArrayList<>();
mCpuUidActiveTimeReader.readDelta(false, (uid, cpuActiveTimesMs) -> {
uid = mapUid(uid);
if (Process.isIsolated(uid)) {
- uidsToRemove.add(uid);
if (DEBUG) Slog.w(TAG, "Got active times for an isolated uid: " + uid);
return;
}
if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
if (DEBUG) Slog.w(TAG, "Got active times for an invalid user's uid " + uid);
- uidsToRemove.add(uid);
return;
}
final Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, startTimeMs);
u.mCpuActiveTimeMs.addCountLocked(cpuActiveTimesMs, onBattery);
});
- for (int uid : uidsToRemove) {
- mCpuUidActiveTimeReader.removeUid(uid);
- }
final long elapsedTimeMs = mClocks.uptimeMillis() - startTimeMs;
if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
@@ -13371,19 +13386,16 @@
@Nullable CpuDeltaPowerAccumulator powerAccumulator) {
final long startTimeMs = mClocks.uptimeMillis();
final long elapsedRealtimeMs = mClocks.elapsedRealtime();
- final List<Integer> uidsToRemove = new ArrayList<>();
// If power is being accumulated for attribution, data needs to be read immediately.
final boolean forceRead = powerAccumulator != null;
mCpuUidClusterTimeReader.readDelta(forceRead, (uid, cpuClusterTimesMs) -> {
uid = mapUid(uid);
if (Process.isIsolated(uid)) {
- uidsToRemove.add(uid);
if (DEBUG) Slog.w(TAG, "Got cluster times for an isolated uid: " + uid);
return;
}
if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
if (DEBUG) Slog.w(TAG, "Got cluster times for an invalid user's uid " + uid);
- uidsToRemove.add(uid);
return;
}
final Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, startTimeMs);
@@ -13393,9 +13405,6 @@
powerAccumulator.addCpuClusterDurationsMs(u, cpuClusterTimesMs);
}
});
- for (int uid : uidsToRemove) {
- mCpuUidClusterTimeReader.removeUid(uid);
- }
final long elapsedTimeMs = mClocks.uptimeMillis() - startTimeMs;
if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
@@ -13562,7 +13571,7 @@
private void startRecordingHistory(final long elapsedRealtimeMs, final long uptimeMs,
boolean reset) {
mRecordingHistory = true;
- mHistoryCur.currentTime = System.currentTimeMillis();
+ mHistoryCur.currentTime = mClocks.currentTimeMillis();
addHistoryBufferLocked(elapsedRealtimeMs,
reset ? HistoryItem.CMD_RESET : HistoryItem.CMD_CURRENT_TIME,
mHistoryCur);
@@ -13604,7 +13613,7 @@
final int chargeFullUah, final long chargeTimeToFullSeconds) {
setBatteryStateLocked(status, health, plugType, level, temp, voltageMv, chargeUah,
chargeFullUah, chargeTimeToFullSeconds,
- mClocks.elapsedRealtime(), mClocks.uptimeMillis(), System.currentTimeMillis());
+ mClocks.elapsedRealtime(), mClocks.uptimeMillis(), mClocks.currentTimeMillis());
}
public void setBatteryStateLocked(final int status, final int health, final int plugType,
@@ -14389,7 +14398,7 @@
}
public void shutdownLocked() {
- recordShutdownLocked(System.currentTimeMillis(), mClocks.elapsedRealtime());
+ recordShutdownLocked(mClocks.currentTimeMillis(), mClocks.elapsedRealtime());
writeSyncLocked();
mShuttingDown = true;
}
@@ -14938,7 +14947,7 @@
startRecordingHistory(elapsedRealtimeMs, uptimeMs, false);
}
- recordDailyStatsIfNeededLocked(false, System.currentTimeMillis());
+ recordDailyStatsIfNeededLocked(false, mClocks.currentTimeMillis());
}
public int describeContents() {
diff --git a/core/java/com/android/internal/os/BatteryUsageStatsProvider.java b/core/java/com/android/internal/os/BatteryUsageStatsProvider.java
index 4989559..d4d6125 100644
--- a/core/java/com/android/internal/os/BatteryUsageStatsProvider.java
+++ b/core/java/com/android/internal/os/BatteryUsageStatsProvider.java
@@ -108,9 +108,9 @@
ArrayList<BatteryUsageStats> results = new ArrayList<>(queries.size());
synchronized (mStats) {
mStats.prepareForDumpLocked();
-
+ final long currentTimeMillis = currentTimeMillis();
for (int i = 0; i < queries.size(); i++) {
- results.add(getBatteryUsageStats(queries.get(i)));
+ results.add(getBatteryUsageStats(queries.get(i), currentTimeMillis));
}
}
return results;
@@ -121,6 +121,11 @@
*/
@VisibleForTesting
public BatteryUsageStats getBatteryUsageStats(BatteryUsageStatsQuery query) {
+ return getBatteryUsageStats(query, currentTimeMillis());
+ }
+
+ private BatteryUsageStats getBatteryUsageStats(BatteryUsageStatsQuery query,
+ long currentTimeMs) {
final long realtimeUs = elapsedRealtime() * 1000;
final long uptimeUs = uptimeMillis() * 1000;
@@ -129,7 +134,10 @@
final BatteryUsageStats.Builder batteryUsageStatsBuilder = new BatteryUsageStats.Builder(
mStats.getCustomEnergyConsumerNames(), includePowerModels);
+ // TODO(b/188068523): use a monotonic clock to ensure resilience of order and duration
+ // of stats sessions to wall-clock adjustments
batteryUsageStatsBuilder.setStatsStartTimestamp(mStats.getStartClockTime());
+ batteryUsageStatsBuilder.setStatsEndTimestamp(currentTimeMs);
SparseArray<? extends BatteryStats.Uid> uidStats = mStats.getUidStats();
for (int i = uidStats.size() - 1; i >= 0; i--) {
@@ -217,4 +225,12 @@
return SystemClock.uptimeMillis();
}
}
+
+ private long currentTimeMillis() {
+ if (mStats instanceof BatteryStatsImpl) {
+ return ((BatteryStatsImpl) mStats).mClocks.currentTimeMillis();
+ } else {
+ return System.currentTimeMillis();
+ }
+ }
}
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 0ea299d..1a23cc1 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -3931,6 +3931,11 @@
applyDecorFitsSystemWindows();
}
+ @Override
+ public boolean decorFitsSystemWindows() {
+ return mDecorFitsSystemWindows;
+ }
+
private void applyDecorFitsSystemWindows() {
ViewRootImpl impl = getViewRootImplOrNull();
if (impl != null) {
diff --git a/core/java/com/android/internal/util/LatencyTracker.java b/core/java/com/android/internal/util/LatencyTracker.java
index 61a5014..358e6ef 100644
--- a/core/java/com/android/internal/util/LatencyTracker.java
+++ b/core/java/com/android/internal/util/LatencyTracker.java
@@ -100,6 +100,11 @@
*/
public static final int ACTION_ROTATE_SCREEN_SENSOR = 9;
+ /**
+ * Time it takes to for the camera based algorithm to rotate the screen.
+ */
+ public static final int ACTION_ROTATE_SCREEN_CAMERA_CHECK = 10;
+
private static final int[] ACTIONS_ALL = {
ACTION_EXPAND_PANEL,
ACTION_TOGGLE_RECENTS,
@@ -110,7 +115,8 @@
ACTION_ROTATE_SCREEN,
ACTION_FACE_WAKE_AND_UNLOCK,
ACTION_START_RECENTS_ANIMATION,
- ACTION_ROTATE_SCREEN_SENSOR
+ ACTION_ROTATE_SCREEN_SENSOR,
+ ACTION_ROTATE_SCREEN_CAMERA_CHECK
};
/** @hide */
@@ -124,7 +130,8 @@
ACTION_ROTATE_SCREEN,
ACTION_FACE_WAKE_AND_UNLOCK,
ACTION_START_RECENTS_ANIMATION,
- ACTION_ROTATE_SCREEN_SENSOR
+ ACTION_ROTATE_SCREEN_SENSOR,
+ ACTION_ROTATE_SCREEN_CAMERA_CHECK
})
@Retention(RetentionPolicy.SOURCE)
public @interface Action {
@@ -140,7 +147,8 @@
FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_ROTATE_SCREEN,
FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_FACE_WAKE_AND_UNLOCK,
FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_START_RECENTS_ANIMATION,
- FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_ROTATE_SCREEN_SENSOR
+ FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_ROTATE_SCREEN_SENSOR,
+ FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_ROTATE_SCREEN_CAMERA_CHECK
};
private static LatencyTracker sLatencyTracker;
@@ -217,6 +225,8 @@
return "ACTION_FACE_WAKE_AND_UNLOCK";
case 9:
return "ACTION_START_RECENTS_ANIMATION";
+ case 10:
+ return "ACTION_ROTATE_SCREEN_CAMERA_CHECK";
case 11:
return "ACTION_ROTATE_SCREEN_SENSOR";
default:
diff --git a/core/java/com/android/internal/util/Preconditions.java b/core/java/com/android/internal/util/Preconditions.java
deleted file mode 100644
index d2d8220..0000000
--- a/core/java/com/android/internal/util/Preconditions.java
+++ /dev/null
@@ -1,771 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.util;
-
-import android.annotation.IntRange;
-import android.annotation.NonNull;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.os.Build;
-import android.text.TextUtils;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Objects;
-
-/**
- * Simple static methods to be called at the start of your own methods to verify
- * correct arguments and state.
- */
-public class Preconditions {
-
- /**
- * Ensures that an expression checking an argument is true.
- *
- * @param expression the expression to check
- * @throws IllegalArgumentException if {@code expression} is false
- */
- @UnsupportedAppUsage
- public static void checkArgument(boolean expression) {
- if (!expression) {
- throw new IllegalArgumentException();
- }
- }
-
- /**
- * Ensures that an expression checking an argument is true.
- *
- * @param expression the expression to check
- * @param errorMessage the exception message to use if the check fails; will
- * be converted to a string using {@link String#valueOf(Object)}
- * @throws IllegalArgumentException if {@code expression} is false
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public static void checkArgument(boolean expression, final Object errorMessage) {
- if (!expression) {
- throw new IllegalArgumentException(String.valueOf(errorMessage));
- }
- }
-
- /**
- * Ensures that an expression checking an argument is true.
- *
- * @param expression the expression to check
- * @param messageTemplate a printf-style message template to use if the check fails; will
- * be converted to a string using {@link String#format(String, Object...)}
- * @param messageArgs arguments for {@code messageTemplate}
- * @throws IllegalArgumentException if {@code expression} is false
- */
- public static void checkArgument(
- final boolean expression,
- final @NonNull String messageTemplate,
- final Object... messageArgs) {
- if (!expression) {
- throw new IllegalArgumentException(String.format(messageTemplate, messageArgs));
- }
- }
-
- /**
- * Ensures that an string reference passed as a parameter to the calling
- * method is not empty.
- *
- * @param string an string reference
- * @return the string reference that was validated
- * @throws IllegalArgumentException if {@code string} is empty
- */
- public static @NonNull <T extends CharSequence> T checkStringNotEmpty(final T string) {
- if (TextUtils.isEmpty(string)) {
- throw new IllegalArgumentException();
- }
- return string;
- }
-
- /**
- * Ensures that an string reference passed as a parameter to the calling
- * method is not empty.
- *
- * @param string an string reference
- * @param errorMessage the exception message to use if the check fails; will
- * be converted to a string using {@link String#valueOf(Object)}
- * @return the string reference that was validated
- * @throws IllegalArgumentException if {@code string} is empty
- */
- public static @NonNull <T extends CharSequence> T checkStringNotEmpty(final T string,
- final Object errorMessage) {
- if (TextUtils.isEmpty(string)) {
- throw new IllegalArgumentException(String.valueOf(errorMessage));
- }
- return string;
- }
-
- /**
- * Ensures that an string reference passed as a parameter to the calling method is not empty.
- *
- * @param string an string reference
- * @param messageTemplate a printf-style message template to use if the check fails; will be
- * converted to a string using {@link String#format(String, Object...)}
- * @param messageArgs arguments for {@code messageTemplate}
- * @return the string reference that was validated
- * @throws IllegalArgumentException if {@code string} is empty
- */
- public static @NonNull <T extends CharSequence> T checkStringNotEmpty(
- final T string,
- final @NonNull String messageTemplate,
- final Object... messageArgs) {
- if (TextUtils.isEmpty(string)) {
- throw new IllegalArgumentException(String.format(messageTemplate, messageArgs));
- }
- return string;
- }
-
- /**
- * Ensures that an object reference passed as a parameter to the calling
- * method is not null.
- *
- * @param reference an object reference
- * @return the non-null reference that was validated
- * @throws NullPointerException if {@code reference} is null
- * @deprecated - use {@link java.util.Objects.requireNonNull} instead.
- */
- @Deprecated
- @UnsupportedAppUsage
- public static @NonNull <T> T checkNotNull(final T reference) {
- if (reference == null) {
- throw new NullPointerException();
- }
- return reference;
- }
-
- /**
- * Ensures that an object reference passed as a parameter to the calling
- * method is not null.
- *
- * @param reference an object reference
- * @param errorMessage the exception message to use if the check fails; will
- * be converted to a string using {@link String#valueOf(Object)}
- * @return the non-null reference that was validated
- * @throws NullPointerException if {@code reference} is null
- * @deprecated - use {@link java.util.Objects#requireNonNull} instead.
- */
- @Deprecated
- @UnsupportedAppUsage
- public static @NonNull <T> T checkNotNull(final T reference, final Object errorMessage) {
- if (reference == null) {
- throw new NullPointerException(String.valueOf(errorMessage));
- }
- return reference;
- }
-
- /**
- * Ensures that an object reference passed as a parameter to the calling
- * method is not null.
- *
- * @param messageTemplate a printf-style message template to use if the check fails; will
- * be converted to a string using {@link String#format(String, Object...)}
- * @param messageArgs arguments for {@code messageTemplate}
- * @throws NullPointerException if {@code reference} is null
- */
- public static @NonNull <T> T checkNotNull(
- final T reference,
- final @NonNull String messageTemplate,
- final Object... messageArgs) {
- if (reference == null) {
- throw new NullPointerException(String.format(messageTemplate, messageArgs));
- }
- return reference;
- }
-
- /**
- * Ensures the truth of an expression involving the state of the calling
- * instance, but not involving any parameters to the calling method.
- *
- * @param expression a boolean expression
- * @throws IllegalStateException if {@code expression} is false
- */
- @UnsupportedAppUsage
- public static void checkState(final boolean expression) {
- checkState(expression, null);
- }
-
- /**
- * Ensures the truth of an expression involving the state of the calling
- * instance, but not involving any parameters to the calling method.
- *
- * @param expression a boolean expression
- * @param errorMessage the exception message to use if the check fails; will
- * be converted to a string using {@link String#valueOf(Object)}
- * @throws IllegalStateException if {@code expression} is false
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public static void checkState(final boolean expression, String errorMessage) {
- if (!expression) {
- throw new IllegalStateException(errorMessage);
- }
- }
-
- /**
- * Ensures the truth of an expression involving the state of the calling
- * instance, but not involving any parameters to the calling method.
- *
- * @param expression a boolean expression
- * @param messageTemplate a printf-style message template to use if the check fails; will
- * be converted to a string using {@link String#format(String, Object...)}
- * @param messageArgs arguments for {@code messageTemplate}
- * @throws IllegalStateException if {@code expression} is false
- */
- public static void checkState(
- final boolean expression,
- final @NonNull String messageTemplate,
- final Object... messageArgs) {
- if (!expression) {
- throw new IllegalStateException(String.format(messageTemplate, messageArgs));
- }
- }
-
- /**
- * Ensures the truth of an expression involving whether the calling identity is authorized to
- * call the calling method.
- *
- * @param expression a boolean expression
- * @throws SecurityException if {@code expression} is false
- */
- public static void checkCallAuthorization(final boolean expression) {
- if (!expression) {
- throw new SecurityException("Calling identity is not authorized");
- }
- }
-
- /**
- * Ensures the truth of an expression involving whether the calling identity is authorized to
- * call the calling method.
- *
- * @param expression a boolean expression
- * @param message the message of the security exception to be thrown
- * @throws SecurityException if {@code expression} is false
- */
- public static void checkCallAuthorization(final boolean expression, final String message) {
- if (!expression) {
- throw new SecurityException(message);
- }
- }
-
- /**
- * Ensures the truth of an expression involving whether the calling identity is authorized to
- * call the calling method.
- *
- * @param expression a boolean expression
- * @param messageTemplate a printf-style message template to use if the check fails; will
- * be converted to a string using {@link String#format(String, Object...)}
- * @param messageArgs arguments for {@code messageTemplate}
- * @throws SecurityException if {@code expression} is false
- */
- public static void checkCallAuthorization(
- final boolean expression,
- final @NonNull String messageTemplate,
- final Object... messageArgs) {
- if (!expression) {
- throw new SecurityException(String.format(messageTemplate, messageArgs));
- }
- }
-
- /**
- * Ensures the truth of an expression involving whether the calling user is authorized to
- * call the calling method.
- *
- * @param expression a boolean expression
- * @throws SecurityException if {@code expression} is false
- */
- public static void checkCallingUser(final boolean expression) {
- if (!expression) {
- throw new SecurityException("Calling user is not authorized");
- }
- }
-
- /**
- * Check the requested flags, throwing if any requested flags are outside
- * the allowed set.
- *
- * @return the validated requested flags.
- */
- public static int checkFlagsArgument(final int requestedFlags, final int allowedFlags) {
- if ((requestedFlags & allowedFlags) != requestedFlags) {
- throw new IllegalArgumentException("Requested flags 0x"
- + Integer.toHexString(requestedFlags) + ", but only 0x"
- + Integer.toHexString(allowedFlags) + " are allowed");
- }
-
- return requestedFlags;
- }
-
- /**
- * Ensures that that the argument numeric value is non-negative (greater than or equal to 0).
- *
- * @param value a numeric int value
- * @param errorMessage the exception message to use if the check fails
- * @return the validated numeric value
- * @throws IllegalArgumentException if {@code value} was negative
- */
- public static @IntRange(from = 0) int checkArgumentNonnegative(final int value,
- final String errorMessage) {
- if (value < 0) {
- throw new IllegalArgumentException(errorMessage);
- }
-
- return value;
- }
-
- /**
- * Ensures that that the argument numeric value is non-negative (greater than or equal to 0).
- *
- * @param value a numeric int value
- *
- * @return the validated numeric value
- * @throws IllegalArgumentException if {@code value} was negative
- */
- public static @IntRange(from = 0) int checkArgumentNonnegative(final int value) {
- if (value < 0) {
- throw new IllegalArgumentException();
- }
-
- return value;
- }
-
- /**
- * Ensures that that the argument numeric value is non-negative (greater than or equal to 0).
- *
- * @param value a numeric long value
- * @return the validated numeric value
- * @throws IllegalArgumentException if {@code value} was negative
- */
- public static long checkArgumentNonnegative(final long value) {
- if (value < 0) {
- throw new IllegalArgumentException();
- }
-
- return value;
- }
-
- /**
- * Ensures that that the argument numeric value is non-negative (greater than or equal to 0).
- *
- * @param value a numeric long value
- * @param errorMessage the exception message to use if the check fails
- * @return the validated numeric value
- * @throws IllegalArgumentException if {@code value} was negative
- */
- public static long checkArgumentNonnegative(final long value, final String errorMessage) {
- if (value < 0) {
- throw new IllegalArgumentException(errorMessage);
- }
-
- return value;
- }
-
- /**
- * Ensures that that the argument numeric value is positive (greater than 0).
- *
- * @param value a numeric int value
- * @param errorMessage the exception message to use if the check fails
- * @return the validated numeric value
- * @throws IllegalArgumentException if {@code value} was not positive
- */
- public static int checkArgumentPositive(final int value, final String errorMessage) {
- if (value <= 0) {
- throw new IllegalArgumentException(errorMessage);
- }
-
- return value;
- }
-
- /**
- * Ensures that the argument floating point value is non-negative (greater than or equal to 0).
- * @param value a floating point value
- * @param errorMessage the exteption message to use if the check fails
- * @return the validated numeric value
- * @throws IllegalArgumentException if {@code value} was negative
- */
- public static float checkArgumentNonNegative(final float value, final String errorMessage) {
- if (value < 0) {
- throw new IllegalArgumentException(errorMessage);
- }
-
- return value;
- }
-
- /**
- * Ensures that the argument floating point value is positive (greater than 0).
- * @param value a floating point value
- * @param errorMessage the exteption message to use if the check fails
- * @return the validated numeric value
- * @throws IllegalArgumentException if {@code value} was not positive
- */
- public static float checkArgumentPositive(final float value, final String errorMessage) {
- if (value <= 0) {
- throw new IllegalArgumentException(errorMessage);
- }
-
- return value;
- }
-
- /**
- * Ensures that the argument floating point value is a finite number.
- *
- * <p>A finite number is defined to be both representable (that is, not NaN) and
- * not infinite (that is neither positive or negative infinity).</p>
- *
- * @param value a floating point value
- * @param valueName the name of the argument to use if the check fails
- *
- * @return the validated floating point value
- *
- * @throws IllegalArgumentException if {@code value} was not finite
- */
- public static float checkArgumentFinite(final float value, final String valueName) {
- if (Float.isNaN(value)) {
- throw new IllegalArgumentException(valueName + " must not be NaN");
- } else if (Float.isInfinite(value)) {
- throw new IllegalArgumentException(valueName + " must not be infinite");
- }
-
- return value;
- }
-
- /**
- * Ensures that the argument floating point value is within the inclusive range.
- *
- * <p>While this can be used to range check against +/- infinity, note that all NaN numbers
- * will always be out of range.</p>
- *
- * @param value a floating point value
- * @param lower the lower endpoint of the inclusive range
- * @param upper the upper endpoint of the inclusive range
- * @param valueName the name of the argument to use if the check fails
- *
- * @return the validated floating point value
- *
- * @throws IllegalArgumentException if {@code value} was not within the range
- */
- public static float checkArgumentInRange(float value, float lower, float upper,
- String valueName) {
- if (Float.isNaN(value)) {
- throw new IllegalArgumentException(valueName + " must not be NaN");
- } else if (value < lower) {
- throw new IllegalArgumentException(
- String.format(
- "%s is out of range of [%f, %f] (too low)", valueName, lower, upper));
- } else if (value > upper) {
- throw new IllegalArgumentException(
- String.format(
- "%s is out of range of [%f, %f] (too high)", valueName, lower, upper));
- }
-
- return value;
- }
-
- /**
- * Ensures that the argument floating point value is within the inclusive range.
- *
- * <p>While this can be used to range check against +/- infinity, note that all NaN numbers
- * will always be out of range.</p>
- *
- * @param value a floating point value
- * @param lower the lower endpoint of the inclusive range
- * @param upper the upper endpoint of the inclusive range
- * @param valueName the name of the argument to use if the check fails
- *
- * @return the validated floating point value
- *
- * @throws IllegalArgumentException if {@code value} was not within the range
- */
- public static double checkArgumentInRange(double value, double lower, double upper,
- String valueName) {
- if (Double.isNaN(value)) {
- throw new IllegalArgumentException(valueName + " must not be NaN");
- } else if (value < lower) {
- throw new IllegalArgumentException(
- String.format(
- "%s is out of range of [%f, %f] (too low)", valueName, lower, upper));
- } else if (value > upper) {
- throw new IllegalArgumentException(
- String.format(
- "%s is out of range of [%f, %f] (too high)", valueName, lower, upper));
- }
-
- return value;
- }
-
- /**
- * Ensures that the argument int value is within the inclusive range.
- *
- * @param value a int value
- * @param lower the lower endpoint of the inclusive range
- * @param upper the upper endpoint of the inclusive range
- * @param valueName the name of the argument to use if the check fails
- *
- * @return the validated int value
- *
- * @throws IllegalArgumentException if {@code value} was not within the range
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public static int checkArgumentInRange(int value, int lower, int upper,
- String valueName) {
- if (value < lower) {
- throw new IllegalArgumentException(
- String.format(
- "%s is out of range of [%d, %d] (too low)", valueName, lower, upper));
- } else if (value > upper) {
- throw new IllegalArgumentException(
- String.format(
- "%s is out of range of [%d, %d] (too high)", valueName, lower, upper));
- }
-
- return value;
- }
-
- /**
- * Ensures that the argument long value is within the inclusive range.
- *
- * @param value a long value
- * @param lower the lower endpoint of the inclusive range
- * @param upper the upper endpoint of the inclusive range
- * @param valueName the name of the argument to use if the check fails
- *
- * @return the validated long value
- *
- * @throws IllegalArgumentException if {@code value} was not within the range
- */
- public static long checkArgumentInRange(long value, long lower, long upper,
- String valueName) {
- if (value < lower) {
- throw new IllegalArgumentException(
- String.format(
- "%s is out of range of [%d, %d] (too low)", valueName, lower, upper));
- } else if (value > upper) {
- throw new IllegalArgumentException(
- String.format(
- "%s is out of range of [%d, %d] (too high)", valueName, lower, upper));
- }
-
- return value;
- }
-
- /**
- * Ensures that the array is not {@code null}, and none of its elements are {@code null}.
- *
- * @param value an array of boxed objects
- * @param valueName the name of the argument to use if the check fails
- *
- * @return the validated array
- *
- * @throws NullPointerException if the {@code value} or any of its elements were {@code null}
- */
- public static <T> T[] checkArrayElementsNotNull(final T[] value, final String valueName) {
- if (value == null) {
- throw new NullPointerException(valueName + " must not be null");
- }
-
- for (int i = 0; i < value.length; ++i) {
- if (value[i] == null) {
- throw new NullPointerException(
- String.format("%s[%d] must not be null", valueName, i));
- }
- }
-
- return value;
- }
-
- /**
- * Ensures that the {@link Collection} is not {@code null}, and none of its elements are
- * {@code null}.
- *
- * @param value a {@link Collection} of boxed objects
- * @param valueName the name of the argument to use if the check fails
- *
- * @return the validated {@link Collection}
- *
- * @throws NullPointerException if the {@code value} or any of its elements were {@code null}
- */
- public static @NonNull <C extends Collection<T>, T> C checkCollectionElementsNotNull(
- final C value, final String valueName) {
- if (value == null) {
- throw new NullPointerException(valueName + " must not be null");
- }
-
- long ctr = 0;
- for (T elem : value) {
- if (elem == null) {
- throw new NullPointerException(
- String.format("%s[%d] must not be null", valueName, ctr));
- }
- ++ctr;
- }
-
- return value;
- }
-
- /**
- * Ensures that the {@link Collection} is not {@code null}, and contains at least one element.
- *
- * @param value a {@link Collection} of boxed elements.
- * @param valueName the name of the argument to use if the check fails.
-
- * @return the validated {@link Collection}
- *
- * @throws NullPointerException if the {@code value} was {@code null}
- * @throws IllegalArgumentException if the {@code value} was empty
- */
- public static <T> Collection<T> checkCollectionNotEmpty(final Collection<T> value,
- final String valueName) {
- if (value == null) {
- throw new NullPointerException(valueName + " must not be null");
- }
- if (value.isEmpty()) {
- throw new IllegalArgumentException(valueName + " is empty");
- }
- return value;
- }
-
- /**
- * Ensures that the given byte array is not {@code null}, and contains at least one element.
- *
- * @param value an array of elements.
- * @param valueName the name of the argument to use if the check fails.
-
- * @return the validated array
- *
- * @throws NullPointerException if the {@code value} was {@code null}
- * @throws IllegalArgumentException if the {@code value} was empty
- */
- @NonNull
- public static byte[] checkByteArrayNotEmpty(final byte[] value, final String valueName) {
- if (value == null) {
- throw new NullPointerException(valueName + " must not be null");
- }
- if (value.length == 0) {
- throw new IllegalArgumentException(valueName + " is empty");
- }
- return value;
- }
-
- /**
- * Ensures that argument {@code value} is one of {@code supportedValues}.
- *
- * @param supportedValues an array of string values
- * @param value a string value
- *
- * @return the validated value
- *
- * @throws NullPointerException if either {@code value} or {@code supportedValues} is null
- * @throws IllegalArgumentException if the {@code value} is not in {@code supportedValues}
- */
- @NonNull
- public static String checkArgumentIsSupported(final String[] supportedValues,
- final String value) {
- checkNotNull(value);
- checkNotNull(supportedValues);
-
- if (!contains(supportedValues, value)) {
- throw new IllegalArgumentException(value + "is not supported "
- + Arrays.toString(supportedValues));
- }
- return value;
- }
-
- private static boolean contains(String[] values, String value) {
- if (values == null) {
- return false;
- }
- for (int i = 0; i < values.length; ++i) {
- if (Objects.equals(value, values[i])) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Ensures that all elements in the argument floating point array are within the inclusive range
- *
- * <p>While this can be used to range check against +/- infinity, note that all NaN numbers
- * will always be out of range.</p>
- *
- * @param value a floating point array of values
- * @param lower the lower endpoint of the inclusive range
- * @param upper the upper endpoint of the inclusive range
- * @param valueName the name of the argument to use if the check fails
- *
- * @return the validated floating point value
- *
- * @throws IllegalArgumentException if any of the elements in {@code value} were out of range
- * @throws NullPointerException if the {@code value} was {@code null}
- */
- public static float[] checkArrayElementsInRange(float[] value, float lower, float upper,
- String valueName) {
- checkNotNull(value, "%s must not be null", valueName);
-
- for (int i = 0; i < value.length; ++i) {
- float v = value[i];
-
- if (Float.isNaN(v)) {
- throw new IllegalArgumentException(valueName + "[" + i + "] must not be NaN");
- } else if (v < lower) {
- throw new IllegalArgumentException(
- String.format("%s[%d] is out of range of [%f, %f] (too low)",
- valueName, i, lower, upper));
- } else if (v > upper) {
- throw new IllegalArgumentException(
- String.format("%s[%d] is out of range of [%f, %f] (too high)",
- valueName, i, lower, upper));
- }
- }
-
- return value;
- }
-
- /**
- * Ensures that all elements in the argument integer array are within the inclusive range
- *
- * @param value an integer array of values
- * @param lower the lower endpoint of the inclusive range
- * @param upper the upper endpoint of the inclusive range
- * @param valueName the name of the argument to use if the check fails
- *
- * @return the validated integer array
- *
- * @throws IllegalArgumentException if any of the elements in {@code value} were out of range
- * @throws NullPointerException if the {@code value} was {@code null}
- */
- public static int[] checkArrayElementsInRange(int[] value, int lower, int upper,
- String valueName) {
- checkNotNull(value, "%s must not be null", valueName);
-
- for (int i = 0; i < value.length; ++i) {
- int v = value[i];
-
- if (v < lower) {
- throw new IllegalArgumentException(
- String.format("%s[%d] is out of range of [%d, %d] (too low)",
- valueName, i, lower, upper));
- } else if (v > upper) {
- throw new IllegalArgumentException(
- String.format("%s[%d] is out of range of [%d, %d] (too high)",
- valueName, i, lower, upper));
- }
- }
-
- return value;
- }
-}
diff --git a/core/jni/android_view_InputEventReceiver.cpp b/core/jni/android_view_InputEventReceiver.cpp
index 44597cc..a699f91 100644
--- a/core/jni/android_view_InputEventReceiver.cpp
+++ b/core/jni/android_view_InputEventReceiver.cpp
@@ -241,13 +241,13 @@
}
// Some other error. Give up
- ALOGW("Failed to send outbound event on channel '%s'. status=%d",
- getInputChannelName().c_str(), status);
+ ALOGW("Failed to send outbound event on channel '%s'. status=%s(%d)",
+ getInputChannelName().c_str(), statusToString(status).c_str(), status);
if (status != DEAD_OBJECT) {
JNIEnv* env = AndroidRuntime::getJNIEnv();
std::string message =
- android::base::StringPrintf("Failed to send outbound event. status=%d",
- status);
+ android::base::StringPrintf("Failed to send outbound event. status=%s(%d)",
+ statusToString(status).c_str(), status);
jniThrowRuntimeException(env, message.c_str());
mMessageQueue->raiseAndClearException(env, "finishInputEvent");
}
@@ -319,8 +319,8 @@
status_t status = mInputConsumer.consume(&mInputEventFactory,
consumeBatches, frameTime, &seq, &inputEvent);
if (status != OK && status != WOULD_BLOCK) {
- ALOGE("channel '%s' ~ Failed to consume input event. status=%d",
- getInputChannelName().c_str(), status);
+ ALOGE("channel '%s' ~ Failed to consume input event. status=%s(%d)",
+ getInputChannelName().c_str(), statusToString(status).c_str(), status);
return status;
}
@@ -502,9 +502,9 @@
receiverWeak, inputChannel, messageQueue);
status_t status = receiver->initialize();
if (status) {
- std::string message =
- android::base::StringPrintf("Failed to initialize input event receiver. status=%d",
- status);
+ std::string message = android::base::
+ StringPrintf("Failed to initialize input event receiver. status=%s(%d)",
+ statusToString(status).c_str(), status);
jniThrowRuntimeException(env, message.c_str());
return 0;
}
@@ -531,7 +531,7 @@
if (status != DEAD_OBJECT) {
std::string message =
android::base::StringPrintf("Failed to finish input event. status=%s(%d)",
- strerror(-status), status);
+ statusToString(status).c_str(), status);
jniThrowRuntimeException(env, message.c_str());
}
}
@@ -564,8 +564,8 @@
&consumedBatch);
if (status && status != DEAD_OBJECT && !env->ExceptionCheck()) {
std::string message =
- android::base::StringPrintf("Failed to consume batched input event. status=%d",
- status);
+ android::base::StringPrintf("Failed to consume batched input event. status=%s(%d)",
+ statusToString(status).c_str(), status);
jniThrowRuntimeException(env, message.c_str());
return JNI_FALSE;
}
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 8df113d..4a1a272 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -826,7 +826,7 @@
PrepareDir(user_source, 0710, user_id ? AID_ROOT : AID_SHELL,
multiuser_get_uid(user_id, AID_EVERYBODY), fail_fn);
- bool isAppDataIsolationEnabled = GetBoolProperty(kVoldAppDataIsolation, true);
+ bool isAppDataIsolationEnabled = GetBoolProperty(kVoldAppDataIsolation, false);
if (mount_mode == MOUNT_EXTERNAL_PASS_THROUGH) {
const std::string pass_through_source = StringPrintf("/mnt/pass_through/%d", user_id);
diff --git a/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp b/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp
index 24fef48..5fe96ed 100644
--- a/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp
+++ b/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp
@@ -402,7 +402,7 @@
socklen_t cred_size = sizeof credentials;
if (getsockopt(n_buffer->getFd(), SOL_SOCKET, SO_PEERCRED, &credentials, &cred_size) == -1
|| cred_size != sizeof credentials) {
- fail_fn_1("ForkMany failed to get initial credentials, %s", strerror(errno));
+ fail_fn_1(CREATE_ERROR("ForkMany failed to get initial credentials, %s", strerror(errno)));
}
bool first_time = true;
@@ -453,7 +453,7 @@
close(session_socket);
int new_fd = accept(zygote_socket_fd, nullptr, nullptr);
if (new_fd == -1) {
- fail_fn_z("Accept(%d) failed: %s", zygote_socket_fd, strerror(errno));
+ fail_fn_z(CREATE_ERROR("Accept(%d) failed: %s", zygote_socket_fd, strerror(errno)));
}
if (new_fd != session_socket) {
// Move new_fd back to the old value, so that we don't have to change Java-level data
diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto
index b157146..fa1e9d4 100644
--- a/core/proto/android/server/windowmanagerservice.proto
+++ b/core/proto/android/server/windowmanagerservice.proto
@@ -221,6 +221,9 @@
optional string name = 2 [ (.android.privacy).dest = DEST_EXPLICIT ];
repeated DisplayAreaChildProto children = 3 [deprecated=true];
optional bool is_task_display_area = 4;
+ optional bool is_root_display_area = 5;
+ optional int32 feature_id = 6;
+ optional bool is_organized = 7;
}
/* represents a generic child of a DisplayArea */
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index ffb8d1d..bb409db 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -593,8 +593,6 @@
<protected-broadcast android:name="android.intent.action.DYNAMIC_SENSOR_CHANGED" />
- <protected-broadcast android:name="android.intent.action.ACTION_RADIO_OFF" />
-
<protected-broadcast android:name="android.accounts.LOGIN_ACCOUNTS_CHANGED" />
<protected-broadcast android:name="android.accounts.action.ACCOUNT_REMOVED" />
<protected-broadcast android:name="android.accounts.action.VISIBLE_ACCOUNTS_CHANGED" />
@@ -2900,6 +2898,12 @@
android:description="@string/permdesc_runInBackground"
android:protectionLevel="normal" />
+ <!-- Allows a companion app to start a foreground service from the background.
+ {@see android.Manifest.permission#REQUEST_COMPANION_RUN_IN_BACKGROUND}
+ -->
+ <permission android:name="android.permission.REQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND"
+ android:protectionLevel="normal"/>
+
<!-- Allows a companion app to use data in the background.
<p>Protection level: normal
-->
@@ -5768,6 +5772,21 @@
android:protectionLevel="normal" />
<uses-permission android:name="android.permission.UPDATE_PACKAGES_WITHOUT_USER_ACTION"/>
+ <!-- Allows an application to take screenshots of layers that normally would be blacked out when
+ a screenshot is taken. Specifically, layers that have the flag
+ {@link android.view.SurfaceControl#SECURE} will be screenshot if the caller requests to
+ capture secure layers. Normally those layers will be rendered black.
+ <p>Not for use by third-party applications.
+ @hide
+ -->
+ <permission android:name="android.permission.CAPTURE_BLACKOUT_CONTENT"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Allows an application to query over global data in AppSearch.
+ @hide -->
+ <permission android:name="android.permission.READ_GLOBAL_APP_SEARCH_DATA"
+ android:protectionLevel="internal|role" />
+
<!-- Attribution for Geofencing service. -->
<attribution android:tag="GeofencingService" android:label="@string/geofencing_service"/>
<!-- Attribution for Country Detector. -->
diff --git a/core/res/OWNERS b/core/res/OWNERS
index 9d739b9..7a8da36 100644
--- a/core/res/OWNERS
+++ b/core/res/OWNERS
@@ -1,6 +1,7 @@
adamp@google.com
alanv@google.com
asc@google.com
+cinek@google.com
dsandler@android.com
dsandler@google.com
dupin@google.com
@@ -8,6 +9,7 @@
hackbod@google.com
ilyamaty@google.com
jaggies@google.com
+jdemeulenaere@google.com
jsharkey@android.com
jsharkey@google.com
juliacr@google.com
@@ -17,7 +19,9 @@
narayan@google.com
ogunwale@google.com
patb@google.com
+shanh@google.com
svetoslavganov@android.com
svetoslavganov@google.com
toddke@google.com
+tsuji@google.com
yamasani@google.com
diff --git a/core/res/res/drawable/work_widget_mask_view_background.xml b/core/res/res/drawable/work_widget_mask_view_background.xml
new file mode 100644
index 0000000..ce9c514
--- /dev/null
+++ b/core/res/res/drawable/work_widget_mask_view_background.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
+ <solid android:color="?android:attr/colorSurfaceVariant" />
+ <corners android:radius="@dimen/system_app_widget_background_radius" />
+</shape>
diff --git a/core/res/res/layout/work_widget_mask_view.xml b/core/res/res/layout/work_widget_mask_view.xml
index e7174cc..a6fb17a 100644
--- a/core/res/res/layout/work_widget_mask_view.xml
+++ b/core/res/res/layout/work_widget_mask_view.xml
@@ -15,17 +15,18 @@
limitations under the License.
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/work_widget_mask_frame"
+ android:id="@android:id/background"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="?android:attr/colorSurfaceVariant"
+ android:background="@drawable/work_widget_mask_view_background"
android:importantForAccessibility="noHideDescendants"
- android:clickable="true">
+ android:clickable="true"
+ android:clipToOutline="true">
<com.android.internal.widget.DisableImageView
android:id="@+id/work_widget_app_icon"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
android:layout_gravity="center"
android:clickable="false" />
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 73adeaa..c9fa462 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -609,14 +609,14 @@
<string-array name="fingerprint_error_vendor">
</string-array>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Vingerafdrukikoon"</string>
- <string name="permlab_manageFace" msgid="4569549381889283282">"bestuur gesigslothardeware"</string>
+ <string name="permlab_manageFace" msgid="4569549381889283282">"bestuur Gesigslothardeware"</string>
<string name="permdesc_manageFace" msgid="6204569688492710471">"Laat program toe om metodes te benut om gesigtemplate vir gebruik by te voeg en uit te vee."</string>
- <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"gebruik gesigslothardeware"</string>
- <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Laat die program toe om gesigslothardeware vir stawing te gebruik"</string>
+ <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"gebruik Gesigslothardeware"</string>
+ <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Laat die program toe om Gesigslothardeware vir stawing te gebruik"</string>
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Gesigslot"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Skryf jou gesig weer in"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Skryf asseblief jou gesig weer in om herkenning te verbeter"</string>
- <string name="face_setup_notification_title" msgid="550617822603450009">"Stel gesigslot op"</string>
+ <string name="face_setup_notification_title" msgid="550617822603450009">"Stel Gesigslot op"</string>
<string name="face_setup_notification_content" msgid="5463999831057751676">"Ontsluit jou foon deur daarna te kyk"</string>
<string name="fingerprint_setup_notification_title" msgid="2002630611398849495">"Stel meer maniere op om te ontsluit"</string>
<string name="fingerprint_setup_notification_content" msgid="205578121848324852">"Tik om \'n vingerafdruk by te voeg"</string>
@@ -643,19 +643,19 @@
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="5085202213036026288">"Kan nie gesig verifieer nie. Hardeware nie beskikbaar nie."</string>
- <string name="face_error_timeout" msgid="522924647742024699">"Probeer gesigslot weer."</string>
+ <string name="face_error_timeout" msgid="522924647742024699">"Probeer Gesigslot weer."</string>
<string name="face_error_no_space" msgid="5649264057026021723">"Kan nie nuwe gesigdata berg nie. Vee eers \'n ou een uit."</string>
<string name="face_error_canceled" msgid="2164434737103802131">"Gesighandeling is gekanselleer."</string>
- <string name="face_error_user_canceled" msgid="8553045452825849843">"Gebruiker het gesigslot gekanselleer."</string>
+ <string name="face_error_user_canceled" msgid="8553045452825849843">"Gebruiker het Gesigslot gekanselleer."</string>
<string name="face_error_lockout" msgid="7864408714994529437">"Te veel pogings. Probeer later weer."</string>
<string name="face_error_lockout_permanent" msgid="8277853602168960343">"Te veel pogings. Gesigslot is gedeaktiveer."</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"Kan nie gesig verifieer nie. Probeer weer."</string>
- <string name="face_error_not_enrolled" msgid="7369928733504691611">"Jy het nie gesigslot opgestel nie."</string>
+ <string name="face_error_not_enrolled" msgid="7369928733504691611">"Jy het nie Gesigslot opgestel nie."</string>
<string name="face_error_hw_not_present" msgid="1070600921591729944">"Gesigslot word nie op hierdie toestel gesteun nie."</string>
<string name="face_error_security_update_required" msgid="5076017208528750161">"Sensor is tydelik gedeaktiveer."</string>
<string name="face_name_template" msgid="3877037340223318119">"Gesig <xliff:g id="FACEID">%d</xliff:g>"</string>
- <string name="face_app_setting_name" msgid="8130135875458467243">"Gebruik gesigslot"</string>
- <string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"Gebruik gesig- of skermslot"</string>
+ <string name="face_app_setting_name" msgid="8130135875458467243">"Gebruik Gesigslot"</string>
+ <string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"Gebruik Gesigslot of Skermslot"</string>
<string name="face_dialog_default_subtitle" msgid="6620492813371195429">"Gebruik jou gesig om voort te gaan"</string>
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Gebruik jou gesig of skermslot om voort te gaan"</string>
<string-array name="face_error_vendor">
@@ -887,7 +887,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Probeer weer"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"Probeer weer"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"Ontsluit vir alle kenmerke en data"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Maksimum gesigontsluit-pogings oorskry"</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Maksimum Gesigslot-pogings oorskry"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"Geen SIM-kaart nie"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"Geen SIM-kaart in tablet nie."</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"Geen SIM-kaart in jou Android TV-toestel nie."</string>
@@ -1713,8 +1713,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Gebruik kortpad"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Kleuromkering"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Kleurkorreksie"</string>
- <!-- no translation found for one_handed_mode_feature_name (2334330034828094891) -->
- <skip />
+ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Eenhandmodus"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Ekstra donker"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Het volumesleutels ingehou. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> aangeskakel."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Het volumesleutels ingehou. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> is afgeskakel"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index f8ff934..4940b80 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -887,7 +887,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"እንደገና ሞክር"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"እንደገና ሞክር"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"ለሁሉም ባህሪያት እና ውሂብ ያስከፍቱ"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"የመጨረሻውን የገጽ ክፈት ሙከራዎችን አልፏል"</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"የመጨረሻውን በመልክ መክፈት ሙከራዎችን አልፏል"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"ምንም ሲም ካርድ የለም"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"በጡባዊ ውስጥ ምንም SIM ካርድ የለም።"</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"በእርስዎ Android TV መሣሪያ ላይ ምንም ሲም ካርድ የለም።"</string>
@@ -957,7 +957,7 @@
<string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"የመክፈቻ አካባቢውን አስፋፋ።"</string>
<string name="keyguard_accessibility_slide_unlock" msgid="2968195219692413046">"በማንሸራተት ክፈት።"</string>
<string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"በስርዓተ-ጥለት መክፈት።"</string>
- <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"በፊት መክፈት።"</string>
+ <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"በመልክ መክፈት።"</string>
<string name="keyguard_accessibility_pin_unlock" msgid="4020864007967340068">"በፒን መክፈት።"</string>
<string name="keyguard_accessibility_sim_pin_unlock" msgid="4895939120871890557">"የሲም ፒን ክፈት።"</string>
<string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"የሲም PUK ክፈት።"</string>
@@ -1869,10 +1869,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"በእርስዎ አስተዳዳሪ ተዘምኗል"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"በእርስዎ አስተዳዳሪ ተሰርዟል"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"እሺ"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"የባትሪ ኃይል ቆጣቢ ጠቆር ያለ ገጽታን ያበራል እና የጀርባ እንቅስቃሴን፣ አንዳንድ ምስላዊ ተጽዕኖዎችን፣ የተወሰኑ ባህሪያትን እና አንዳንድ አውታረ መረብ ግንኙነቶችን ይገድባል ወይም ያጠፋል።\n\n"<annotation id="url">"የበለጠ ለመረዳት"</annotation></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>
@@ -1975,10 +1973,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> አሁን ላይ አይገኝም። በ<xliff:g id="APP_NAME_1">%2$s</xliff:g> የሚተዳደር ነው።"</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"የበለጠ ለመረዳት"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"መተግበሪያን ላፍታ እንዳይቆም አድርግ"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"የሥራ መተግበሪያዎች ይብሩ?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"የእርስዎን የሥራ መተግበሪያዎች እና ማሳወቂያዎች መዳረሻ ያግኙ"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"አብራ"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"መተግበሪያ አይገኝም"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> አሁን አይገኝም።"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index c2be67c..6d44d15 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -621,14 +621,14 @@
<string-array name="fingerprint_error_vendor">
</string-array>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"رمز بصمة الإصبع"</string>
- <string name="permlab_manageFace" msgid="4569549381889283282">"إدارة أجهزة \"فتح القفل بالوجه\""</string>
+ <string name="permlab_manageFace" msgid="4569549381889283282">"إدارة أجهزة ميزة \"فتح الجهاز بالتعرف على الوجه\""</string>
<string name="permdesc_manageFace" msgid="6204569688492710471">"السماح للتطبيق باستدعاء طرق لإضافة نماذج من الوجوه وحذفها"</string>
- <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"استخدام أجهزة \"فتح القفل بالوجه\""</string>
- <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"السماح للتطبيق باستخدام أجهزة \"فتح القفل بالوجه\" لإجراء المصادقة"</string>
- <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"فتح القفل بالوجه"</string>
+ <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"استخدام أجهزة ميزة \"فتح الجهاز بالتعرف على الوجه\""</string>
+ <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"السماح للتطبيق باستخدام أجهزة ميزة \"فتح الجهاز بالتعرف على الوجه\" لإجراء المصادقة"</string>
+ <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"فتح الجهاز بالتعرف على الوجه"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"إعادة تسجيل وجهك"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"لتحسين قدرة الجهاز على معرفة وجهك، يُرجى إعادة تسجيل الوجه."</string>
- <string name="face_setup_notification_title" msgid="550617822603450009">"إعداد ميزة \"فتح القفل بالوجه\""</string>
+ <string name="face_setup_notification_title" msgid="550617822603450009">"إعداد ميزة \"فتح الجهاز بالتعرف على الوجه\""</string>
<string name="face_setup_notification_content" msgid="5463999831057751676">"يمكنك فتح قفل هاتفك بمجرّد النظر إلى الشاشة."</string>
<string name="fingerprint_setup_notification_title" msgid="2002630611398849495">"إعداد المزيد من الطرق لفتح قفل الجهاز"</string>
<string name="fingerprint_setup_notification_content" msgid="205578121848324852">"انقر لإضافة بصمة إصبع."</string>
@@ -655,19 +655,19 @@
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="5085202213036026288">"يتعذّر التحقُّق من الوجه. الجهاز غير مُتاح."</string>
- <string name="face_error_timeout" msgid="522924647742024699">"حاول استخدام \"فتح القفل بالوجه\" مرة أخرى."</string>
+ <string name="face_error_timeout" msgid="522924647742024699">"جرِّب استخدام ميزة \"فتح الجهاز بالتعرف على الوجه\" مرة أخرى."</string>
<string name="face_error_no_space" msgid="5649264057026021723">"يتعذَّر تخزين بيانات الوجه الجديد. احذف الوجه القديم أولاً."</string>
<string name="face_error_canceled" msgid="2164434737103802131">"تمّ إلغاء عملية مصادقة الوجه."</string>
- <string name="face_error_user_canceled" msgid="8553045452825849843">"ألغى المستخدم \"فتح القفل بالوجه\"."</string>
+ <string name="face_error_user_canceled" msgid="8553045452825849843">"ألغى المستخدم ميزة \"فتح الجهاز بالتعرف على الوجه\"."</string>
<string name="face_error_lockout" msgid="7864408714994529437">"تمّ إجراء محاولات كثيرة. أعِد المحاولة لاحقًا."</string>
- <string name="face_error_lockout_permanent" msgid="8277853602168960343">"تم إجراء عدد كبير جدًا من المحاولات. وتم إيقاف \"فتح القفل بالوجه\"."</string>
+ <string name="face_error_lockout_permanent" msgid="8277853602168960343">"تم إجراء محاولات كثيرة، ولذا تم إيقاف ميزة \"فتح الجهاز بالتعرف على الوجه\"."</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"يتعذّر التحقق من الوجه. حاول مرة أخرى."</string>
- <string name="face_error_not_enrolled" msgid="7369928733504691611">"لم يسبق لك إعداد \"فتح القفل بالوجه\"."</string>
- <string name="face_error_hw_not_present" msgid="1070600921591729944">"\"فتح القفل بالوجه\" غير متوفر على هذا الجهاز."</string>
+ <string name="face_error_not_enrolled" msgid="7369928733504691611">"لم يسبق لك إعداد ميزة \"فتح الجهاز بالتعرف على الوجه\"."</string>
+ <string name="face_error_hw_not_present" msgid="1070600921591729944">"ميزة \"فتح الجهاز بالتعرف على الوجه\" غير متوفرة بهذا الجهاز."</string>
<string name="face_error_security_update_required" msgid="5076017208528750161">"تم إيقاف جهاز الاستشعار مؤقتًا."</string>
<string name="face_name_template" msgid="3877037340223318119">"الوجه <xliff:g id="FACEID">%d</xliff:g>"</string>
- <string name="face_app_setting_name" msgid="8130135875458467243">"استخدام \"فتح القفل بالوجه\""</string>
- <string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"استخدام ميزة \"فتح القفل بالوجه\" أو ميزة \"قفل الشاشة\""</string>
+ <string name="face_app_setting_name" msgid="8130135875458467243">"فتح الجهاز بالتعرف على الوجه"</string>
+ <string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"استخدام ميزة \"فتح الجهاز بالتعرف على الوجه\" أو ميزة \"قفل الشاشة\""</string>
<string name="face_dialog_default_subtitle" msgid="6620492813371195429">"استخدِم الوجه للمتابعة"</string>
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"استخدام ميزة \"فتح القفل بالوجه\" أو ميزة \"قفل الشاشة\" للمتابعة"</string>
<string-array name="face_error_vendor">
@@ -899,7 +899,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"أعد المحاولة"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"أعد المحاولة"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"فتح قفل جميع الميزات والبيانات"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"تم تجاوز الحد الأقصى لعدد محاولات تأمين الجهاز بالوجه"</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"تم تجاوز الحد الأقصى لعدد محاولات فتح الجهاز بالتعرف على الوجه"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"ليست هناك شريحة SIM"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"ليس هناك شريحة SIM في الجهاز اللوحي."</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"لا تتوفر شريحة SIM في جهاز Android TV."</string>
@@ -969,7 +969,7 @@
<string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"توسيع منطقة فتح القفل."</string>
<string name="keyguard_accessibility_slide_unlock" msgid="2968195219692413046">"فتح القفل باستخدام التمرير."</string>
<string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"فتح القفل باستخدام النقش."</string>
- <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"تأمين الجهاز بالوجه."</string>
+ <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"استخدام ميزة \"فتح الجهاز بالتعرف على الوجه\""</string>
<string name="keyguard_accessibility_pin_unlock" msgid="4020864007967340068">"فتح القفل باستخدام رمز PIN."</string>
<string name="keyguard_accessibility_sim_pin_unlock" msgid="4895939120871890557">"فتح قفل رقم التعريف الشخصي لشريحة SIM."</string>
<string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"فتح قفل مفتاح PUK لشريحة SIM."</string>
@@ -1034,8 +1034,7 @@
<string name="text_copied" msgid="2531420577879738860">"تم نسخ النص إلى الحافظة."</string>
<string name="copied" msgid="4675902854553014676">"تم النسخ."</string>
<string name="pasted_from_app" msgid="5627698450808256545">"تم لصق محتوى في <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> من <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>."</string>
- <!-- no translation found for pasted_from_clipboard (7355790625710831847) -->
- <skip />
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"لصَق تطبيق <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> محتوىً من الحافظة."</string>
<string name="pasted_text" msgid="4298871641549173733">"لصق تطبيق <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> النص الذي نسخته."</string>
<string name="pasted_image" msgid="4729097394781491022">"لصق تطبيق <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> الصورة التي نسختها."</string>
<string name="pasted_content" msgid="646276353060777131">"لصق تطبيق <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> المحتوى الذي نسخته."</string>
@@ -1340,14 +1339,10 @@
<string name="android_preparing_apk" msgid="589736917792300956">"جارٍ تحضير <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"بدء التطبيقات."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"جارٍ إعادة التشغيل."</string>
- <!-- no translation found for fp_enrollment_powerbutton_intent_title (3385634173366119903) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_message (6582149052513682522) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_positive_button (5963520983910436791) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_negative_button (6465764183480190748) -->
- <skip />
+ <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="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>
@@ -1806,8 +1801,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"استخدام الاختصار"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"قلب الألوان"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"تصحيح الألوان"</string>
- <!-- no translation found for one_handed_mode_feature_name (2334330034828094891) -->
- <skip />
+ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"وضع \"التصفح بيد واحدة\""</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"زيادة تعتيم الشاشة"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"تم الضغط مع الاستمرار على مفتاحَي التحكّم في مستوى الصوت. تم تفعيل <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"تم الضغط مع الاستمرار على مفتاحَي التحكّم في مستوى الصوت. تم إيقاف <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
@@ -1967,10 +1961,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"تم التحديث بواسطة المشرف"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"تم الحذف بواسطة المشرف"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"حسنًا"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"يؤدي استخدام ميزة \"توفير شحن البطارية\" إلى تفعيل وضع \"المظهر الداكن\" وتقييد أو إيقاف الأنشطة في الخلفية وبعض التأثيرات المرئية وميزات معيّنة وبعض اتصالات الشبكات.\n\n"<annotation id="url">"مزيد من المعلومات"</annotation></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>
@@ -2109,10 +2101,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"التطبيق <xliff:g id="APP_NAME_0">%1$s</xliff:g> غير متاح الآن، وهو مُدار بواسطة <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"مزيد من المعلومات"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"استئناف تشغيل التطبيق"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"هل تريد تفعيل تطبيقات العمل؟"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"الوصول إلى تطبيقات العمل وإشعاراتها"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"تفعيل"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"التطبيق غير متاح"</string>
<string name="app_blocked_message" msgid="542972921087873023">"تطبيق <xliff:g id="APP_NAME">%1$s</xliff:g> غير متاح الآن."</string>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index 8101c28..569b628 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -609,14 +609,14 @@
<string-array name="fingerprint_error_vendor">
</string-array>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"ফিংগাৰপ্ৰিণ্ট আইকন"</string>
- <string name="permlab_manageFace" msgid="4569549381889283282">"মুখাৱয়বৰদ্বাৰা আনলক হার্ডৱেৰ পৰিচালনা কৰক"</string>
+ <string name="permlab_manageFace" msgid="4569549381889283282">"ফেচ আনলক হার্ডৱেৰ পৰিচালনা কৰক"</string>
<string name="permdesc_manageFace" msgid="6204569688492710471">"মুখমণ্ডলৰ টেম্প্লেট যোগ কৰাৰ বা মচাৰ পদ্ধতি কামত লগাবলৈ আহ্বান কৰিবলৈ এপটোক অনুমতি দিয়ে।"</string>
- <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"মুখাৱয়বৰদ্বাৰা আনলক হার্ডৱেৰ ব্যৱহাৰ কৰক"</string>
- <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"বিশ্বাসযোগ্যতা প্ৰমাণীকৰণৰ বাবে এপ্ক মুখাৱয়বৰদ্বাৰা আনলক কৰা হাৰ্ডৱেৰ ব্যৱহাৰ কৰিবলৈ দিয়ে"</string>
- <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"মুখাৱয়বৰদ্বাৰা আনলক কৰা সুবিধা"</string>
+ <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"ফেচ আনলক হার্ডৱেৰ ব্যৱহাৰ কৰক"</string>
+ <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"বিশ্বাসযোগ্যতা প্ৰমাণীকৰণৰ বাবে এপ্ক ফেচ আনলক কৰা হাৰ্ডৱেৰ ব্যৱহাৰ কৰিবলৈ দিয়ে"</string>
+ <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"ফেচ আনলক কৰা সুবিধা"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"আপোনাৰ মুখমণ্ডল পুনৰ পঞ্জীয়ণ কৰক"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"চিনাক্তকৰণৰ সুবিধাটো উন্নত কৰিবলৈ, অনুগ্ৰহ কৰি আপোনাৰ মুখমণ্ডল পুনৰ পঞ্জীয়ন কৰক"</string>
- <string name="face_setup_notification_title" msgid="550617822603450009">"মুখাৱয়বৰদ্বাৰা আনলক কৰা সুবিধাটো ছেট আপ কৰক"</string>
+ <string name="face_setup_notification_title" msgid="550617822603450009">"ফেচ আনলক সুবিধাটো ছেট আপ কৰক"</string>
<string name="face_setup_notification_content" msgid="5463999831057751676">"আপোনাৰ ফ’নটোলৈ চাই সেইটো আনলক কৰক"</string>
<string name="fingerprint_setup_notification_title" msgid="2002630611398849495">"আনলক কৰাৰ অধিক উপায় ছেট আপ কৰক"</string>
<string name="fingerprint_setup_notification_content" msgid="205578121848324852">"এটা ফিংগাৰপ্ৰিণ্ট যোগ দিবলৈ টিপক"</string>
@@ -643,19 +643,19 @@
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="5085202213036026288">"মুখমণ্ডল সত্যাপন কৰিব পৰা নগ’ল। হাৰ্ডৱেৰ নাই।"</string>
- <string name="face_error_timeout" msgid="522924647742024699">"পুনৰ মুখাৱয়বৰদ্বাৰা আনলক কৰি চাওক।"</string>
+ <string name="face_error_timeout" msgid="522924647742024699">"পুনৰ ফেচ আনলক কৰি চাওক।"</string>
<string name="face_error_no_space" msgid="5649264057026021723">"নতুন মুখমণ্ডলৰ ডেটা জমা কৰিব পৰা নাই। প্ৰথমে পুৰণি এখন মচক।"</string>
<string name="face_error_canceled" msgid="2164434737103802131">"মুখমণ্ডলৰ প্ৰক্ৰিয়া বাতিল কৰা হ’ল।"</string>
- <string name="face_error_user_canceled" msgid="8553045452825849843">"ব্যৱহাৰকাৰীয়ে মুখাৱয়বৰদ্বাৰা আনলক কৰাটো বাতিল কৰিছে।"</string>
+ <string name="face_error_user_canceled" msgid="8553045452825849843">"ব্যৱহাৰকাৰীয়ে ফেচ আনলক কৰাটো বাতিল কৰিছে।"</string>
<string name="face_error_lockout" msgid="7864408714994529437">"অত্যধিক ভুল প্ৰয়াস। কিছুসময়ৰ পাছত আকৌ চেষ্টা কৰক।"</string>
- <string name="face_error_lockout_permanent" msgid="8277853602168960343">"অতি বেছি প্ৰয়াস। মুখাৱয়বৰদ্বাৰা আনলক কৰাটো অক্ষম কৰা হৈছে।"</string>
+ <string name="face_error_lockout_permanent" msgid="8277853602168960343">"অতি বেছি প্ৰয়াস। ফেচ আনলক কৰাটো অক্ষম কৰা হৈছে।"</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"মুখমণ্ডল সত্যাপন কৰিব পৰা নগ’ল। আকৌ চেষ্টা কৰক।"</string>
- <string name="face_error_not_enrolled" msgid="7369928733504691611">"আপুনি মুখাৱয়বৰদ্বাৰা আনলক কৰাটো ছেট আপ কৰা নাই।"</string>
- <string name="face_error_hw_not_present" msgid="1070600921591729944">"এই ডিভাইচটোত মুখাৱয়বৰদ্বাৰা আনলক কৰা সুবিধাটো নচলে।"</string>
+ <string name="face_error_not_enrolled" msgid="7369928733504691611">"আপুনি ফেচ আনলক ছেট আপ কৰা নাই।"</string>
+ <string name="face_error_hw_not_present" msgid="1070600921591729944">"এই ডিভাইচটোত ফেচ আনলক কৰা সুবিধাটো নচলে।"</string>
<string name="face_error_security_update_required" msgid="5076017208528750161">"ছেন্সৰটো সাময়িকভাৱে অক্ষম হৈ আছে।"</string>
<string name="face_name_template" msgid="3877037340223318119">"মুখমণ্ডল <xliff:g id="FACEID">%d</xliff:g>"</string>
- <string name="face_app_setting_name" msgid="8130135875458467243">"মুখাৱয়বৰে আনলক কৰা ব্যৱহাৰ কৰক"</string>
- <string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"মুখাৱয়বৰে আনলক কৰা অথবা স্ক্ৰীন লক ব্যৱহাৰ কৰক"</string>
+ <string name="face_app_setting_name" msgid="8130135875458467243">"ফেচ আনলক ব্যৱহাৰ কৰক"</string>
+ <string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"ফেচ আনলক অথবা স্ক্ৰীন লক ব্যৱহাৰ কৰক"</string>
<string name="face_dialog_default_subtitle" msgid="6620492813371195429">"অব্যাহত ৰাখিবলৈ নিজৰ মুখাৱয়ব ব্যৱহাৰ কৰক"</string>
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"অব্যাহত ৰাখিবলৈ আপোনাৰ মুখাৱয়ব অথবা স্ক্ৰীন লক ব্যৱহাৰ কৰক"</string>
<string-array name="face_error_vendor">
@@ -887,7 +887,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"আকৌ চেষ্টা কৰক"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"আকৌ চেষ্টা কৰক"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"সকলো সুবিধা আৰু ডেটাৰ বাবে আনলক কৰক"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"গৰাকীৰ মুখাৱয়বৰ দ্বাৰা আনলক কৰা সর্বধিক সীমা অতিক্ৰম কৰা হ’ল"</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"গৰাকীৰ ফেচ আনলক কৰা সৰ্বাধিক সীমা অতিক্ৰম কৰা হ’ল"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"কোনো ছিম কাৰ্ড নাই"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"টে\'বলেটত ছিম কার্ড নাই।"</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"আপোনাৰ Android TV ডিভাইচটোত কোনো ছিম কার্ড নাই।"</string>
@@ -957,7 +957,7 @@
<string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"আনলক ক্ষেত্ৰ বিস্তাৰ কৰক।"</string>
<string name="keyguard_accessibility_slide_unlock" msgid="2968195219692413046">"শ্লাইডৰদ্বাৰা আনলক।"</string>
<string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"আৰ্হিৰদ্বাৰা আনলক।"</string>
- <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"মুখাৱয়বৰদ্বাৰা আনলক।"</string>
+ <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"ফেচ আনলক।"</string>
<string name="keyguard_accessibility_pin_unlock" msgid="4020864007967340068">"পিনৰদ্বাৰা আনলক।"</string>
<string name="keyguard_accessibility_sim_pin_unlock" msgid="4895939120871890557">"ছিম পিন আনলক।"</string>
<string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"ছিম পিইউকে আনলক।"</string>
@@ -1022,8 +1022,7 @@
<string name="text_copied" msgid="2531420577879738860">"ক্লিপব\'র্ডলৈ বাৰ্তা প্ৰতিলিপি কৰা হ’ল।"</string>
<string name="copied" msgid="4675902854553014676">"প্ৰতিলিপি কৰা হ’ল"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>ৰ পৰা <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> পে’ষ্ট কৰা হৈছে"</string>
- <!-- no translation found for pasted_from_clipboard (7355790625710831847) -->
- <skip />
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>এ আপোনাৰ ক্লিপব’ৰ্ডৰ পৰা পে’ষ্ট কৰিছে"</string>
<string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>এ আপুনি প্ৰতিলিপি কৰা সমল পে’ষ্ট কৰিছে"</string>
<string name="pasted_image" msgid="4729097394781491022">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>এ আপুনি প্ৰতিলিপি কৰা এটা প্ৰতিচ্ছবি পে’ষ্ট কৰিছে"</string>
<string name="pasted_content" msgid="646276353060777131">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>এ আপুনি প্ৰতিলিপি কৰা সমল পে’ষ্ট কৰিছে"</string>
@@ -1260,14 +1259,10 @@
<string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g>সাজু কৰি থকা হৈছে।"</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"আৰম্ভ হৈ থকা এপসমূহ।"</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"বুট কাৰ্য সমাপ্ত কৰিছে।"</string>
- <!-- no translation found for fp_enrollment_powerbutton_intent_title (3385634173366119903) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_message (6582149052513682522) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_positive_button (5963520983910436791) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_negative_button (6465764183480190748) -->
- <skip />
+ <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="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>
@@ -1874,10 +1869,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"আপোনাৰ প্ৰশাসকে আপেডট কৰিছে"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"আপোনাৰ প্ৰশাসকে মচিছে"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ঠিক আছে"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"বেটাৰী সঞ্চয়কাৰীয়ে গাঢ় ৰঙৰ থীম অন কৰে আৰু নেপথ্যৰ কাৰ্যকলাপ, কিছুমান ভিজুৱেল ইফেক্ট, নিৰ্দিষ্ট কিছুমান সুবিধা আৰু নেটৱৰ্কৰ সংযোগ সীমিত অথবা অফ কৰে।\n\n"<annotation id="url">"অধিক জানক"</annotation></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>
@@ -1980,10 +1973,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"এই মুহূৰ্তত <xliff:g id="APP_NAME_0">%1$s</xliff:g> উপলব্ধ নহয়। ইয়াক <xliff:g id="APP_NAME_1">%2$s</xliff:g>এ পৰিচালনা কৰে।"</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"অধিক জানক"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"এপ্ আনপজ কৰক"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"কাম সম্পৰ্কীয় এপ্ অন কৰিবনে?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"আপোনাৰ কাম সম্পৰ্কীয় এপ্ আৰু জাননীৰ এক্সেছ পাওক"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"অন কৰক"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"এপ্টো উপলব্ধ নহয়"</string>
<string name="app_blocked_message" msgid="542972921087873023">"এই মুহূৰ্তত <xliff:g id="APP_NAME">%1$s</xliff:g> উপলব্ধ নহয়।"</string>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index e8abac1..6552e82 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -609,11 +609,11 @@
<string-array name="fingerprint_error_vendor">
</string-array>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Barmaq izi ikonası"</string>
- <string name="permlab_manageFace" msgid="4569549381889283282">"üz kilidi avadanlığını idarə edin"</string>
+ <string name="permlab_manageFace" msgid="4569549381889283282">"Üz ilə kiliddən açma avadanlığını idarə edin"</string>
<string name="permdesc_manageFace" msgid="6204569688492710471">"Proqramdan istifadə üçün barmaq izi şablonlarını əlavə etmək və silmək məqsədilə üsullara müraciət etməyə imkan verir."</string>
- <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"üz kilidi avadanlığından istifadə edin"</string>
- <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"İdentifikasiya üçün tətbiqin üz kilidi avadanlığından istifadə etməsinə icazə verir"</string>
- <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Üz kilidi"</string>
+ <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"üz ilə kiliddən açma işlədin"</string>
+ <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"İdentifikasiya üçün tətbiqin Üz ilə Kiliddən Açmasına icazə verir"</string>
+ <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Üz ilə Kiliddən Açma"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Üzünüzü yenidən qeydiyyatdan keçirin"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Tanınmanı təkmilləşdirmək üçün üzünüzü yenidən qeydiyyatdan keçirin"</string>
<string name="face_setup_notification_title" msgid="550617822603450009">"Üz ilə kiliddən çıxarmanı ayarlayın"</string>
@@ -643,15 +643,15 @@
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="5085202213036026288">"Üz doğrulanmadı. Avadanlıq əlçatan deyil."</string>
- <string name="face_error_timeout" msgid="522924647742024699">"Üz kilidini yenidən sınayın."</string>
+ <string name="face_error_timeout" msgid="522924647742024699">"Üz ilə Kiliddən Açmanı yenidən sınayın."</string>
<string name="face_error_no_space" msgid="5649264057026021723">"Yeni üz datası saxlanmadı. Əvvəlcə köhnə olanı silin."</string>
<string name="face_error_canceled" msgid="2164434737103802131">"Üz əməliyyatı ləğv edildi."</string>
- <string name="face_error_user_canceled" msgid="8553045452825849843">"İstifadəçi üz kilidini ləğv edib."</string>
+ <string name="face_error_user_canceled" msgid="8553045452825849843">"İstifadəçi Üz ilə Kiliddən Açmanı ləğv edib."</string>
<string name="face_error_lockout" msgid="7864408714994529437">"Həddindən çox cəhd. Sonraya saxlayın."</string>
- <string name="face_error_lockout_permanent" msgid="8277853602168960343">"Həddindən çox cəhd. Üz kilidi deaktiv edildi."</string>
+ <string name="face_error_lockout_permanent" msgid="8277853602168960343">"Həddindən çox cəhd. Üz ilə Kiliddən Açma deaktiv edildi."</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"Üz doğrulanmadı. Yenidən cəhd edin."</string>
- <string name="face_error_not_enrolled" msgid="7369928733504691611">"Üz kilidi quraşdırmamısınız."</string>
- <string name="face_error_hw_not_present" msgid="1070600921591729944">"Üz kilidi bu cihazda dəstəklənmir."</string>
+ <string name="face_error_not_enrolled" msgid="7369928733504691611">"Üz ilə Kiliddən Açmanı quraşdırmamısınız."</string>
+ <string name="face_error_hw_not_present" msgid="1070600921591729944">"Üz ilə Kiliddən Açma bu cihazda dəstəklənmir."</string>
<string name="face_error_security_update_required" msgid="5076017208528750161">"Sensor müvəqqəti deaktivdir."</string>
<string name="face_name_template" msgid="3877037340223318119">"Üz <xliff:g id="FACEID">%d</xliff:g>"</string>
<string name="face_app_setting_name" msgid="8130135875458467243">"Üz ilə kiliddən çıxarmadan istifadə edin"</string>
@@ -887,7 +887,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Bir də cəhd edin"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"Bir daha cəhd et"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"Bütün funksiyalar və data üçün kiliddən çıxarın"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Sifət kilidi cəhdləriniz bitdi"</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Üz ilə Kiliddən Açma cəhdləriniz bitdi"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"SIM kart yoxdur."</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"Planşetdə SIM kart yoxdur."</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"Android TV cihazında SIM kart yoxdur."</string>
@@ -957,7 +957,7 @@
<string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"Kilidi açma sahəsini genişləndir."</string>
<string name="keyguard_accessibility_slide_unlock" msgid="2968195219692413046">"Sürüşdürmə kilidi."</string>
<string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"Kild açma modeli."</string>
- <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"Sifət Kilidi"</string>
+ <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"Üz ilə Kiliddən Açma"</string>
<string name="keyguard_accessibility_pin_unlock" msgid="4020864007967340068">"Pin kilid açması."</string>
<string name="keyguard_accessibility_sim_pin_unlock" msgid="4895939120871890557">"Sim Pin kilidini açın."</string>
<string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"Sim Puk kilidini açın."</string>
@@ -1022,8 +1022,7 @@
<string name="text_copied" msgid="2531420577879738860">"Mətn panoya kopyalandı."</string>
<string name="copied" msgid="4675902854553014676">"Kopyalandı"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> tətbiqindən əlavə edilib"</string>
- <!-- no translation found for pasted_from_clipboard (7355790625710831847) -->
- <skip />
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> mübadilə buferinizdən əlavə edilib"</string>
<string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> kopyaladığınız mətni əlavə etdi"</string>
<string name="pasted_image" msgid="4729097394781491022">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> kopyaladığınız şəkli əlavə etdi"</string>
<string name="pasted_content" msgid="646276353060777131">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> kopyaladığınız kontenti əlavə etdi"</string>
@@ -1260,14 +1259,10 @@
<string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> proqramının hazırlanması."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Tətbiqlər başladılır."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Yükləmə başa çatır."</string>
- <!-- no translation found for fp_enrollment_powerbutton_intent_title (3385634173366119903) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_message (6582149052513682522) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_positive_button (5963520983910436791) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_negative_button (6465764183480190748) -->
- <skip />
+ <string name="fp_enrollment_powerbutton_intent_title" msgid="3385634173366119903">"Ekran deaktiv edilsin?"</string>
+ <string name="fp_enrollment_powerbutton_intent_message" msgid="6582149052513682522">"Barmaq izinizi ayarlayarkən Qidalanma düyməsinə basdınız.\n\nBu, adətən ekranınızı deaktiv edir."</string>
+ <string name="fp_enrollment_powerbutton_intent_positive_button" msgid="5963520983910436791">"Deaktiv edin"</string>
+ <string name="fp_enrollment_powerbutton_intent_negative_button" msgid="6465764183480190748">"Ləğv edin"</string>
<string name="heavy_weight_notification" msgid="8382784283600329576">"<xliff:g id="APP">%1$s</xliff:g> çalışır"</string>
<string name="heavy_weight_notification_detail" msgid="6802247239468404078">"Oyuna qayıtmaq üçün klikləyin"</string>
<string name="heavy_weight_switcher_title" msgid="3861984210040100886">"Oyun seçin"</string>
@@ -1718,8 +1713,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Qısayol İstifadə edin"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Rəng İnversiyası"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Rəng korreksiyası"</string>
- <!-- no translation found for one_handed_mode_feature_name (2334330034828094891) -->
- <skip />
+ <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="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>
@@ -1875,10 +1869,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Admin tərəfindən yeniləndi"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Admin tərəfindən silindi"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"Enerjiyə Qənaət rejimi Tünd temanı aktivləşdirir, habelə arxa fon fəaliyyətini, bəzi vizual effektləri, müəyyən xüsusiyyətləri və bəzi şəbəkə bağlantılarını məhdudlaşdırır, yaxud söndürür.\n\n"<annotation id="url">"Ətraflı məlumat"</annotation></string>
+ <string name="battery_saver_description" msgid="8518809702138617167">"Enerjiyə Qənaət rejimi Tünd temanı aktivləşdirir, habelə arxa fon fəaliyyətini, bəzi vizual effektləri, müəyyən xüsusiyyətləri və bəzi şəbəkə bağlantılarını məhdudlaşdırır, yaxud söndürür."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Mobil interneti qənaətlə işlətmək məqsədilə Data Qanaəti bəzi tətbiqlərin fonda data göndərməsinin və qəbulunun qarşısını alır. Hazırda işlətdiyiniz tətbiq nisbətən az müntəzəmliklə data istifadə edə bilər. Örnək olaraq bu, o deməkdir ki, şəkil fayllarına toxunmadıqca onlar açılmayacaq."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Trafikə qənaət edilsin?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"Aktivləşdirin"</string>
@@ -1981,10 +1973,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> hazırda əlçatan deyil. Bunu <xliff:g id="APP_NAME_1">%2$s</xliff:g> idarə edir."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"Ətraflı məlumat"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Tətbiqi davam etdirin"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"İş tətbiqləri aktiv edilsin?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"İş tətbiqlərinizə və bildirişlərinizə giriş əldə edin"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Aktivləşdirin"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"Tətbiq əlçatan deyil"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> hazırda əlçatan deyil."</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 2681451..91ac488 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -1892,10 +1892,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Ažurirao je administrator"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Izbrisao je administrator"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"Potvrdi"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"Ušteda baterije uključuje Tamnu temu i ograničava ili isključuje aktivnosti u pozadini, neke vizuelne efekte, određene funkcije i mrežne veze.\n\n"<annotation id="url">"Saznajte više"</annotation></string>
+ <string name="battery_saver_description" msgid="8518809702138617167">"Ušteda baterije uključuje tamnu temu i ograničava ili isključuje aktivnosti u pozadini, neke vizuelne efekte, određene funkcije i neke mrežne veze."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Da bi se smanjila potrošnja podataka, Ušteda podataka sprečava neke aplikacije da šalju ili primaju podatke u pozadini. Aplikacija koju trenutno koristite može da pristupa podacima, ali će to činiti ređe. Na primer, slike se neće prikazivati dok ih ne dodirnete."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Želite da uključite Uštedu podataka?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"Uključi"</string>
@@ -2007,10 +2005,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"Aplikacija <xliff:g id="APP_NAME_0">%1$s</xliff:g> trenutno nije dostupna. <xliff:g id="APP_NAME_1">%2$s</xliff:g> upravlja dostupnošću."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"Saznajte više"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Opozovi pauziranje aplikacije"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"Uključiti poslovne aplikacije?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"Pristupajte poslovnim aplikacijama i obaveštenjima"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Uključi"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"Aplikacija nije dostupna"</string>
<string name="app_blocked_message" msgid="542972921087873023">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> trenutno nije dostupna."</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 9f7fc35..24243e4 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -893,7 +893,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Паўтарыце спробу"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"Паўтарыце спробу"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"Разблакіраваць для ўсіх функцый і даных"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Перавышана максімальная колькасць спроб разблакоўкі праз Фэйскантроль"</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Перавышана максімальная колькасць спроб разблакоўкі праз распазнаванне твару"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"Няма SIM-карты"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"Няма SIM-карты ў планшэце."</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"У вашай прыладзе Android TV няма SIM-карты."</string>
@@ -1028,8 +1028,7 @@
<string name="text_copied" msgid="2531420577879738860">"Тэкст скапіраваны ў буфер абмену."</string>
<string name="copied" msgid="4675902854553014676">"Скапіравана"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"Праграма \"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>\" была ўстаўлена з праграмы \"<xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>\""</string>
- <!-- no translation found for pasted_from_clipboard (7355790625710831847) -->
- <skip />
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"Праграма (\"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>\") уставіла даныя з буфера абмену"</string>
<string name="pasted_text" msgid="4298871641549173733">"Скапіраваны вамі тэкст устаўлены праграмай \"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>\""</string>
<string name="pasted_image" msgid="4729097394781491022">"Скапіраваны вамі відарыс устаўлены праграмай \"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>\""</string>
<string name="pasted_content" msgid="646276353060777131">"Скапіраванае вамі змесціва ўстаўлена праграмай \"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>\""</string>
@@ -1300,14 +1299,10 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Падрыхтоўка <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Запуск прыкладанняў."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Завяршэнне загрузкі."</string>
- <!-- no translation found for fp_enrollment_powerbutton_intent_title (3385634173366119903) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_message (6582149052513682522) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_positive_button (5963520983910436791) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_negative_button (6465764183480190748) -->
- <skip />
+ <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="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>
@@ -1762,8 +1757,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Выкарыстоўваць камбінацыю хуткага доступу"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Інверсія колераў"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Карэкцыя колераў"</string>
- <!-- no translation found for one_handed_mode_feature_name (2334330034828094891) -->
- <skip />
+ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Рэжым кіравання адной рукой"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Дадатковае памяншэнне яркасці"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Клавішы гучнасці ўтрымліваліся націснутымі. Уключана служба \"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\"."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Клавішы гучнасці ўтрымліваліся націснутымі. Служба \"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\" выключана."</string>
@@ -1921,10 +1915,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Абноўлены вашым адміністратарам"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Выдалены вашым адміністратарам"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ОК"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"У рэжыме эканоміі зараду ўключаецца цёмная тэма і выключаюцца ці абмяжоўваюцца дзеянні ў фонавым рэжыме, некаторыя візуальныя эфекты, пэўныя функцыі і падключэнні да сетак.\n\n"<annotation id="url">"Даведацца больш"</annotation></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>
@@ -2045,10 +2037,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"Праграма \"<xliff:g id="APP_NAME_0">%1$s</xliff:g>\" цяпер недаступная. Яна кіруецца праграмай \"<xliff:g id="APP_NAME_1">%2$s</xliff:g>\"."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"Даведацца больш"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Скасаваць прыпыненне для праграмы"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"Уключыць працоўныя праграмы?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"Атрымаць доступ да працоўных праграм і апавяшчэнняў"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Уключыць"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"Праграма недаступная"</string>
<string name="app_blocked_message" msgid="542972921087873023">"Праграма \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" цяпер недаступная."</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 619dcb7..d82f189 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1022,8 +1022,7 @@
<string name="text_copied" msgid="2531420577879738860">"Текстът е копиран в буферната памет."</string>
<string name="copied" msgid="4675902854553014676">"Копирано"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> постави данни от <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>"</string>
- <!-- no translation found for pasted_from_clipboard (7355790625710831847) -->
- <skip />
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> постави данни от буферната памет"</string>
<string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> постави копиран от вас текст"</string>
<string name="pasted_image" msgid="4729097394781491022">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> постави копирано от вас изображение"</string>
<string name="pasted_content" msgid="646276353060777131">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> постави копирано от вас съдържание"</string>
@@ -1260,14 +1259,10 @@
<string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> се подготвя."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Приложенията се стартират."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Зареждането завършва."</string>
- <!-- no translation found for fp_enrollment_powerbutton_intent_title (3385634173366119903) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_message (6582149052513682522) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_positive_button (5963520983910436791) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_negative_button (6465764183480190748) -->
- <skip />
+ <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="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>
@@ -1874,10 +1869,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Актуализирано от администратора ви"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Изтрито от администратора ви"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ОК"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"Режимът за запазване на батерията включва тъмната тема и ограничава или изключва активността на заден план, някои визуални ефекти, определени функции и някои връзки с мрежата.\n\n"<annotation id="url">"Научете повече"</annotation></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>
@@ -1980,10 +1973,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"В момента няма достъп до <xliff:g id="APP_NAME_0">%1$s</xliff:g>. Това се управлява от <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"Научете повече"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Отмяна на паузата за приложението"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"Включване на служ. приложения?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"Получете достъп до служебните си приложения и известия"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Включване"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"Приложението не е достъпно"</string>
<string name="app_blocked_message" msgid="542972921087873023">"В момента няма достъп до <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index 9dedb88..b1be0ca 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -609,14 +609,14 @@
<string-array name="fingerprint_error_vendor">
</string-array>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"আঙ্গুলের ছাপ আইকন"</string>
- <string name="permlab_manageFace" msgid="4569549381889283282">"মুখের সাহায্যে আনলক করার হার্ডওয়্যার ম্যানেজ করা"</string>
+ <string name="permlab_manageFace" msgid="4569549381889283282">"ফেস আনলক হার্ডওয়্যার ম্যানেজ করা"</string>
<string name="permdesc_manageFace" msgid="6204569688492710471">"ব্যবহার করার জন্য ফেস টেম্পলেট যোগ করা এবং মোছার পদ্ধতি গ্রহণ করতে অ্যাপটিকে অনুমতি দেয়৷"</string>
- <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"মুখের সাহায্যে আনলক করার হার্ডওয়্যার ব্যবহার করা"</string>
- <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"অ্যাপকে যাচাইকরণের জন্য মুখের সাহায্যে আনলক করার হার্ডওয়্যার ব্যবহার করতে দেয়"</string>
- <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"মুখের সাহায্যে আনলক"</string>
+ <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"ফেস আনলক হার্ডওয়্যার ব্যবহার করা"</string>
+ <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"অ্যাপকে যাচাইকরণের জন্য ফেস আনলক হার্ডওয়্যার ব্যবহার করতে দেয়"</string>
+ <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"ফেস আনলক"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"আপনার ফেস আবার এনরোল করুন"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"শনাক্তকরণের উন্নতি করতে আপনার ফেস আবার এনরোল করুন"</string>
- <string name="face_setup_notification_title" msgid="550617822603450009">"মুখের সাহায্যে আনলক করার ফিচার সেট-আপ করুন"</string>
+ <string name="face_setup_notification_title" msgid="550617822603450009">"ফেস আনলক ফিচার সেট-আপ করুন"</string>
<string name="face_setup_notification_content" msgid="5463999831057751676">"আপনার ফোনের দিকে তাকিয়ে এটিকে আনলক করুন"</string>
<string name="fingerprint_setup_notification_title" msgid="2002630611398849495">"আনলক করার জন্য বিভিন্ন উপায়ে সেট আপ করুন"</string>
<string name="fingerprint_setup_notification_content" msgid="205578121848324852">"একটি আঙ্গুলের ছাপ যোগ করতে ট্যাপ করুন"</string>
@@ -643,19 +643,19 @@
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="5085202213036026288">"ফেস যাচাই করা যায়নি। হার্ডওয়্যার উপলভ্য নেই।"</string>
- <string name="face_error_timeout" msgid="522924647742024699">"আবার মুখের সাহায্যে আনলক করার চেষ্টা করুন।"</string>
+ <string name="face_error_timeout" msgid="522924647742024699">"আবার ফেস আনলকের মাধ্যমে চেষ্টা করুন।"</string>
<string name="face_error_no_space" msgid="5649264057026021723">"নতুন ফেস ডেটা স্টোর করা যায়নি। প্রথমে পুরনোটি মুছে ফেলুন।"</string>
<string name="face_error_canceled" msgid="2164434737103802131">"ফেস অপারেশন বাতিল করা হয়েছে৷"</string>
- <string name="face_error_user_canceled" msgid="8553045452825849843">"ব্যবহারকারী মুখের সাহায্যে আনলক বাতিল করে দিয়েছেন।"</string>
+ <string name="face_error_user_canceled" msgid="8553045452825849843">"ব্যবহারকারী ফেস আনলক বাতিল করে দিয়েছেন।"</string>
<string name="face_error_lockout" msgid="7864408714994529437">"অনেকবার চেষ্টা করা হয়েছে। পরে আবার চেষ্টা করুন।"</string>
- <string name="face_error_lockout_permanent" msgid="8277853602168960343">"অনেকবার চেষ্টা করেছেন। মুখের সাহায্যে আনলক করার সুবিধা বন্ধ করা হয়েছে।"</string>
+ <string name="face_error_lockout_permanent" msgid="8277853602168960343">"অনেকবার চেষ্টা করেছেন। ফেস আনলক বন্ধ করা হয়েছে।"</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"আপনার মুখ যাচাই করা যাচ্ছে না। আবার চেষ্টা করুন।"</string>
- <string name="face_error_not_enrolled" msgid="7369928733504691611">"এখনও মুখের সাহায্যে আনলক করার সুবিধা সেট-আপ করেননি।"</string>
- <string name="face_error_hw_not_present" msgid="1070600921591729944">"এই ডিভাইসে মুখের সাহায্যে আনলক করার সুবিধাটি কাজ করে না।"</string>
+ <string name="face_error_not_enrolled" msgid="7369928733504691611">"এখনও ফেস আনলক সেট-আপ করেননি।"</string>
+ <string name="face_error_hw_not_present" msgid="1070600921591729944">"এই ডিভাইসে ফেস আনলক সুবিধাটি কাজ করে না।"</string>
<string name="face_error_security_update_required" msgid="5076017208528750161">"সেন্সর অস্থায়ীভাবে বন্ধ করা আছে।"</string>
<string name="face_name_template" msgid="3877037340223318119">"<xliff:g id="FACEID">%d</xliff:g> ফেস"</string>
- <string name="face_app_setting_name" msgid="8130135875458467243">"মুখের সাহায্যে আনলক ব্যবহার করুন"</string>
- <string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"মুখ অথবা স্ক্রিন লক ব্যবহার করুন"</string>
+ <string name="face_app_setting_name" msgid="8130135875458467243">"ফেস আনলক ব্যবহার করুন"</string>
+ <string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"ফেস অথবা স্ক্রিন লক ব্যবহার করুন"</string>
<string name="face_dialog_default_subtitle" msgid="6620492813371195429">"চালিয়ে যেতে আপনার মুখ ব্যবহার করুন"</string>
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"চালিয়ে যেতে আপনার ফেস বা স্ক্রিন লক ব্যবহার করুন"</string>
<string-array name="face_error_vendor">
@@ -887,7 +887,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"আবার চেষ্টা করুন"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"আবার চেষ্টা করুন"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"সমস্ত বৈশিষ্ট্য এবং ডেটার জন্য আনলক করুন"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"মুখের সাহায্যে আনলক করার প্রচেষ্টা যতবার করা যায় তার সীমা পেরিয়ে গেছে"</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"ফেস আনলক ফিচারের সাহায্যে আনলকের চেষ্টা সর্বোচ্চ সীমা পেরিয়ে গেছে"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"কোনো সিম কার্ড নেই"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"ট্যাবলেটের মধ্যে কোনো সিম কার্ড নেই৷"</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"আপনার Android TV ডিভাইসে কোনও সিম কার্ড নেই।"</string>
@@ -957,7 +957,7 @@
<string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"আনলক এলাকা প্রসারিত করুন৷"</string>
<string name="keyguard_accessibility_slide_unlock" msgid="2968195219692413046">"স্লাইড দিয়ে আনলক৷"</string>
<string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"প্যাটার্ন দিয়ে আনলক৷"</string>
- <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"মুখের সাহায্যে আনলক৷"</string>
+ <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"ফেস আনলক৷"</string>
<string name="keyguard_accessibility_pin_unlock" msgid="4020864007967340068">"পিন দিয়ে আনলক৷"</string>
<string name="keyguard_accessibility_sim_pin_unlock" msgid="4895939120871890557">"সিম পিন আনলক।"</string>
<string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"সিম পিইউকে আনলক।"</string>
@@ -1713,8 +1713,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"শর্টকাট ব্যবহার করুন"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"রঙ উল্টানো"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"রঙ সংশোধন"</string>
- <!-- no translation found for one_handed_mode_feature_name (2334330034828094891) -->
- <skip />
+ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"এক হাতে ব্যবহার করার মোড"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"অতিরিক্ত কম আলো"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ভলিউম কী ধরে ছিলেন। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> চালু করা হয়েছে।"</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"ভলিউম কী ধরে ছিলেন। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> বন্ধ করা হয়েছে।"</string>
@@ -1870,10 +1869,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"আপনার প্রশাসক আপডেট করেছেন"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"আপনার প্রশাসক মুছে দিয়েছেন"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ঠিক আছে"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"ব্যাটারি সেভার ডার্ক থিম চালু করে এবং ব্যাকগ্রাউন্ড অ্যাক্টিভিটি, কিছু ভিজ্যুয়াল এফেক্ট, নির্দিষ্ট ফিচার ও কয়েকটি নেটওয়ার্ক কানেকশনের ব্যবহার সীমিত করে বা বন্ধ করে দেয়।\n\n"<annotation id="url">"আরও জানুন"</annotation></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>
@@ -1976,10 +1973,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> এখন উপলভ্য নয়। এই অ্যাপটিকে <xliff:g id="APP_NAME_1">%2$s</xliff:g> অ্যাপ ম্যানেজ করে।"</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"আরও জানুন"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"অ্যাপ আবার চালু করুন"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"অফিস অ্যাপ চালু করবেন?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"আপনার অফিস অ্যাপ এবং বিজ্ঞপ্তিতে অ্যাক্সেস পান"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"চালু করুন"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"অ্যাপ পাওয়া যাচ্ছে না"</string>
<string name="app_blocked_message" msgid="542972921087873023">"এই মুহূর্তে <xliff:g id="APP_NAME">%1$s</xliff:g> অ্যাপ পাওয়া যাচ্ছে না।"</string>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index c918d8c..35f5e4b 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -1892,10 +1892,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Ažurirao je vaš administrator"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Izbrisao je vaš administrator"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"Uredu"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"Ušteda baterije uključuje Tamnu temu i ograničava ili isključuje aktivnost u pozadini, određene vizuelne efekte i funkcije te neke mrežne veze.\n\n"<annotation id="url">"Saznajte više"</annotation></string>
+ <string name="battery_saver_description" msgid="8518809702138617167">"Ušteda baterije uključuje Tamnu temu i ograničava ili isključuje aktivnost u pozadini, određene vizuelne efekte i funkcije i neke mrežne veze."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Radi smanjenja prijenosa podataka, Ušteda podataka sprečava da neke aplikacije šalju ili primaju podatke u pozadini. Aplikacija koju trenutno koristite može pristupiti podacima, ali će to činiti rjeđe. Naprimjer, to može značiti da se slike ne prikazuju dok ih ne dodirnete."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Uključiti Uštedu podataka?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"Uključi"</string>
@@ -2007,10 +2005,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"Aplikacija <xliff:g id="APP_NAME_0">%1$s</xliff:g> trenutno nije dostupna. Ovim upravlja aplikacija <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"Saznajte više"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Ponovo aktiviraj aplikaciju"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"Uključiti poslovne aplikacije?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"Pristupite poslovnim aplikacijama i obavještenjima"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Uključi"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"Aplikacija nije dostupna"</string>
<string name="app_blocked_message" msgid="542972921087873023">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> trenutno nije dostupna."</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 402402f..2b16b36 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -609,10 +609,10 @@
<string-array name="fingerprint_error_vendor">
</string-array>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Icona d\'empremta digital"</string>
- <string name="permlab_manageFace" msgid="4569549381889283282">"gestiona el maquinari de desbloqueig facial"</string>
+ <string name="permlab_manageFace" msgid="4569549381889283282">"gestiona el maquinari de Desbloqueig facial"</string>
<string name="permdesc_manageFace" msgid="6204569688492710471">"Permet que l\'aplicació afegeixi i suprimeixi plantilles de cares que es puguin fer servir."</string>
- <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"utilitza el maquinari de desbloqueig facial"</string>
- <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Permet que l\'aplicació faci servir el maquinari de desbloqueig facial per a l\'autenticació"</string>
+ <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"utilitza el maquinari de Desbloqueig facial"</string>
+ <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Permet que l\'aplicació faci servir el maquinari de Desbloqueig facial per a l\'autenticació"</string>
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Desbloqueig facial"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Torna a registrar la cara"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Per millorar el reconeixement, torna a registrar la cara"</string>
@@ -648,7 +648,7 @@
<string name="face_error_canceled" msgid="2164434737103802131">"S\'ha cancel·lat el reconeixement facial."</string>
<string name="face_error_user_canceled" msgid="8553045452825849843">"L\'usuari ha cancel·lat el desbloqueig facial."</string>
<string name="face_error_lockout" msgid="7864408714994529437">"Massa intents. Torna-ho a provar més tard."</string>
- <string name="face_error_lockout_permanent" msgid="8277853602168960343">"Massa intents. S\'ha desactivat el desbloqueig facial."</string>
+ <string name="face_error_lockout_permanent" msgid="8277853602168960343">"Massa intents. S\'ha desactivat Desbloqueig facial."</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"No es pot verificar la cara. Torna-ho a provar."</string>
<string name="face_error_not_enrolled" msgid="7369928733504691611">"No has configurat el desbloqueig facial"</string>
<string name="face_error_hw_not_present" msgid="1070600921591729944">"El desbloqueig facial no és compatible amb el dispositiu."</string>
@@ -887,7 +887,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Torna-ho a provar"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"Torna-ho a provar"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"Desbl. per accedir a totes les funcions i dades"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"S\'ha superat el nombre màxim d\'intents de desbloqueig facial"</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"S\'ha superat el nombre màxim d\'intents de Desbloqueig facial"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"No hi ha cap SIM"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"No hi ha cap SIM a la tauleta."</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"No hi ha cap targeta SIM al dispositiu Android TV."</string>
@@ -1713,8 +1713,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Utilitza la drecera"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Inversió de colors"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Correcció de color"</string>
- <!-- no translation found for one_handed_mode_feature_name (2334330034828094891) -->
- <skip />
+ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Mode d\'una mà"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Atenuació extra"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"S\'han mantingut premudes les tecles de volum. S\'ha activat <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"S\'han mantingut premudes les tecles de volum. S\'ha desactivat <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
@@ -1870,10 +1869,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Actualitzat per l\'administrador"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Suprimit per l\'administrador"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"D\'acord"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"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.\n\n"<annotation id="url">"Més informació"</annotation></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_button" msgid="4399405762586419726">"Activa"</string>
@@ -1976,10 +1973,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> no està disponible en aquests moments. Aquesta opció es gestiona a <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"Més informació"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Reactiva l\'aplicació"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"Activar aplicacions de treball?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"Accedeix a les teves aplicacions de treball i a les notificacions"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Activa"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"L\'aplicació no està disponible"</string>
<string name="app_blocked_message" msgid="542972921087873023">"Ara mateix, <xliff:g id="APP_NAME">%1$s</xliff:g> no està disponible."</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 17ddb0e..0ae3e7a 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -656,7 +656,7 @@
<string name="face_error_lockout" msgid="7864408714994529437">"Příliš mnoho pokusů. Zkuste to později."</string>
<string name="face_error_lockout_permanent" msgid="8277853602168960343">"Příliš mnoho pokusů. Odemknutí obličejem bylo deaktivováno."</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"Obličej se nepodařilo ověřit. Zkuste to znovu."</string>
- <string name="face_error_not_enrolled" msgid="7369928733504691611">"Ověření obličejem nemáte nastavené."</string>
+ <string name="face_error_not_enrolled" msgid="7369928733504691611">"Odemknutí obličejem nemáte nastavené."</string>
<string name="face_error_hw_not_present" msgid="1070600921591729944">"Odemknutí obličejem na tomto zařízení není podporováno."</string>
<string name="face_error_security_update_required" msgid="5076017208528750161">"Senzor je dočasně deaktivován."</string>
<string name="face_name_template" msgid="3877037340223318119">"Obličej <xliff:g id="FACEID">%d</xliff:g>"</string>
@@ -1915,10 +1915,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Aktualizováno administrátorem"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Smazáno administrátorem"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"Spořič baterie zapíná tmavý motiv a omezuje či vypíná aktivitu na pozadí, některé vizuální efekty, některé funkce a připojení k některým sítím.\n\n"<annotation id="url">"Další informace"</annotation></string>
+ <string name="battery_saver_description" msgid="8518809702138617167">"Spořič baterie zapíná tmavý motiv a omezuje či vypíná aktivitu na pozadí, některé vizuální efekty, některé funkce a připojení k některým sítím."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Z důvodu snížení využití dat brání spořič dat některým aplikacím v odesílání nebo příjmu dat na pozadí. Aplikace, kterou právě používáte, data přenášet může, ale může tak činit méně často. V důsledku toho se například obrázky nemusejí zobrazit, dokud na ně neklepnete."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Chcete zapnout Spořič dat?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"Zapnout"</string>
@@ -2039,10 +2037,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"Aplikace <xliff:g id="APP_NAME_0">%1$s</xliff:g> momentálně není dostupná. Tato předvolba se spravuje v aplikaci <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"Další informace"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Zrušit pozastavení aplikace"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"Zapnout pracovní aplikace?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"Získejte přístup ke svým pracovním aplikacím a oznámením"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Zapnout"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"Aplikace není k dispozici"</string>
<string name="app_blocked_message" msgid="542972921087873023">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> v tuto chvíli není k dispozici."</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index d4aced53..432a7c7 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -887,7 +887,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Prøv igen"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"Prøv igen"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"Lås op for at se alle funktioner og data"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Det maksimale antal forsøg på at bruge Ansigtslås er overskredet"</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Det maksimale antal forsøg på at bruge ansigtslås er overskredet"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"Intet SIM-kort"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"Der er ikke noget SIM-kort i tabletcomputeren."</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"Der er intet SIM-kort i din Android TV-enhed."</string>
@@ -957,7 +957,7 @@
<string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"Udvid oplåsningsområdet."</string>
<string name="keyguard_accessibility_slide_unlock" msgid="2968195219692413046">"Lås op ved at stryge."</string>
<string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"Lås op med mønster."</string>
- <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"Lås op med ansigt."</string>
+ <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"Ansigtslås."</string>
<string name="keyguard_accessibility_pin_unlock" msgid="4020864007967340068">"Lås op med pinkode."</string>
<string name="keyguard_accessibility_sim_pin_unlock" msgid="4895939120871890557">"Lås op ved hjælp af pinkoden til SIM-kortet."</string>
<string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"Lås op ved hjælp af PUK-koden til SIM-kortet."</string>
@@ -1713,8 +1713,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Brug genvej"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Ombytning af farver"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Farvekorrigering"</string>
- <!-- no translation found for one_handed_mode_feature_name (2334330034828094891) -->
- <skip />
+ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Enhåndstilstand"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Ekstra dæmpet belysning"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Lydstyrkeknapperne blev holdt nede. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> er aktiveret."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Lydstyrkeknapperne blev holdt nede. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> er deaktiveret."</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index bd01896..bc8dafb 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -609,14 +609,14 @@
<string-array name="fingerprint_error_vendor">
</string-array>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Fingerabdruck-Symbol"</string>
- <string name="permlab_manageFace" msgid="4569549381889283282">"Face Unlock-Hardware verwalten"</string>
+ <string name="permlab_manageFace" msgid="4569549381889283282">"Hardware für Gesichtsentsperrung verwalten"</string>
<string name="permdesc_manageFace" msgid="6204569688492710471">"Ermöglicht der App, Gesichtsvorlagen hinzuzufügen oder zu entfernen."</string>
- <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"Face Unlock-Hardware verwenden"</string>
- <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Ermöglicht der App, zu Authentifizierungszwecken Face Unlock-Hardware zu verwenden"</string>
- <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Face Unlock"</string>
+ <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"Hardware für Gesichtsentsperrung verwenden"</string>
+ <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Ermöglicht der App, zur Authentifizierung Hardware für Gesichtsentsperrung zu verwenden"</string>
+ <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Gesichtsentsperrung"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Gesicht neu scannen lassen"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Für bessere Erkennung Gesicht neu scannen lassen"</string>
- <string name="face_setup_notification_title" msgid="550617822603450009">"Face Unlock einrichten"</string>
+ <string name="face_setup_notification_title" msgid="550617822603450009">"Gesichtsentsperrung einrichten"</string>
<string name="face_setup_notification_content" msgid="5463999831057751676">"Entsperre dein Smartphone, indem du es ansiehst"</string>
<string name="fingerprint_setup_notification_title" msgid="2002630611398849495">"Weitere Möglichkeiten zum Entsperren einrichten"</string>
<string name="fingerprint_setup_notification_content" msgid="205578121848324852">"Tippe, um einen Fingerabdruck hinzuzufügen"</string>
@@ -643,19 +643,19 @@
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="5085202213036026288">"Gesicht nicht erkannt. Hardware nicht verfügbar."</string>
- <string name="face_error_timeout" msgid="522924647742024699">"Face Unlock noch einmal versuchen."</string>
+ <string name="face_error_timeout" msgid="522924647742024699">"Gesichtsentsperrung noch einmal versuchen."</string>
<string name="face_error_no_space" msgid="5649264057026021723">"Kein Speicherplatz frei. Bitte erst ein Gesicht löschen."</string>
<string name="face_error_canceled" msgid="2164434737103802131">"Gesichtserkennung abgebrochen."</string>
- <string name="face_error_user_canceled" msgid="8553045452825849843">"Face Unlock vom Nutzer abgebrochen."</string>
+ <string name="face_error_user_canceled" msgid="8553045452825849843">"Gesichtsentsperrung vom Nutzer abgebrochen."</string>
<string name="face_error_lockout" msgid="7864408714994529437">"Zu viele Versuche, bitte später noch einmal versuchen"</string>
- <string name="face_error_lockout_permanent" msgid="8277853602168960343">"Zu viele Versuche. Face Unlock wurde deaktiviert."</string>
+ <string name="face_error_lockout_permanent" msgid="8277853602168960343">"Zu viele Versuche. Gesichtsentsperrung wurde deaktiviert."</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"Gesichtsprüfung nicht möglich. Noch mal versuchen."</string>
- <string name="face_error_not_enrolled" msgid="7369928733504691611">"Face Unlock ist nicht eingerichtet."</string>
- <string name="face_error_hw_not_present" msgid="1070600921591729944">"Face Unlock wird auf diesem Gerät nicht unterstützt."</string>
+ <string name="face_error_not_enrolled" msgid="7369928733504691611">"Gesichtsentsperrung ist nicht eingerichtet."</string>
+ <string name="face_error_hw_not_present" msgid="1070600921591729944">"Gesichtsentsperrung wird auf diesem Gerät nicht unterstützt."</string>
<string name="face_error_security_update_required" msgid="5076017208528750161">"Der Sensor ist vorübergehend deaktiviert."</string>
<string name="face_name_template" msgid="3877037340223318119">"Gesicht <xliff:g id="FACEID">%d</xliff:g>"</string>
- <string name="face_app_setting_name" msgid="8130135875458467243">"Face Unlock verwenden"</string>
- <string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"Face Unlock oder Displaysperre verwenden"</string>
+ <string name="face_app_setting_name" msgid="8130135875458467243">"Gesichtsentsperrung verwenden"</string>
+ <string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"Gesichtsentsperrung oder Displaysperre verwenden"</string>
<string name="face_dialog_default_subtitle" msgid="6620492813371195429">"Gesichtserkennung verwenden, um fortzufahren"</string>
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Verwende die Gesichtserkennung oder deine Display-Entsperrmethode, um fortzufahren"</string>
<string-array name="face_error_vendor">
@@ -887,7 +887,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Erneut versuchen"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"Erneut versuchen"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"Entsperren, um alle Funktionen und Daten zu nutzen"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Die maximal zulässige Anzahl an Face Unlock-Versuchen wurde überschritten."</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Die maximal zulässige Anzahl an Versuchen zur Gesichtsentsperrung wurde überschritten."</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"Keine SIM-Karte"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"Keine SIM-Karte im Tablet"</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"Keine SIM-Karte in deinem Android TV-Gerät."</string>
@@ -957,7 +957,7 @@
<string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"Entsperr-Bereich maximieren"</string>
<string name="keyguard_accessibility_slide_unlock" msgid="2968195219692413046">"Entsperrung mit Fingerbewegung"</string>
<string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"Entsperrung mit Muster"</string>
- <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"Face Unlock"</string>
+ <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"Gesichtsentsperrung"</string>
<string name="keyguard_accessibility_pin_unlock" msgid="4020864007967340068">"Entsperrung mit PIN"</string>
<string name="keyguard_accessibility_sim_pin_unlock" msgid="4895939120871890557">"SIM durch PIN-Eingabe entsperren."</string>
<string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"SIM durch PUK-Eingabe entsperren."</string>
@@ -1022,8 +1022,7 @@
<string name="text_copied" msgid="2531420577879738860">"Text in Zwischenablage kopiert."</string>
<string name="copied" msgid="4675902854553014676">"Kopiert"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> hat etwas von <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> eingefügt"</string>
- <!-- no translation found for pasted_from_clipboard (7355790625710831847) -->
- <skip />
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> aus der Zwischenablage eingefügt"</string>
<string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> hat einen von dir kopierten Text eingefügt"</string>
<string name="pasted_image" msgid="4729097394781491022">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> hat ein von dir kopiertes Bild eingefügt"</string>
<string name="pasted_content" msgid="646276353060777131">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> hat den von dir kopierten Inhalt eingefügt"</string>
@@ -1260,14 +1259,10 @@
<string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> wird vorbereitet"</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Apps werden gestartet..."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Start wird abgeschlossen..."</string>
- <!-- no translation found for fp_enrollment_powerbutton_intent_title (3385634173366119903) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_message (6582149052513682522) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_positive_button (5963520983910436791) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_negative_button (6465764183480190748) -->
- <skip />
+ <string name="fp_enrollment_powerbutton_intent_title" msgid="3385634173366119903">"Display ausschalten?"</string>
+ <string name="fp_enrollment_powerbutton_intent_message" msgid="6582149052513682522">"Beim Einrichten deines Fingerabdrucks hast du die Ein-/Aus-Taste gedrückt.\n\nDamit wird üblicherweise das Display ausgeschaltet."</string>
+ <string name="fp_enrollment_powerbutton_intent_positive_button" msgid="5963520983910436791">"Ausschalten"</string>
+ <string name="fp_enrollment_powerbutton_intent_negative_button" msgid="6465764183480190748">"Abbrechen"</string>
<string name="heavy_weight_notification" msgid="8382784283600329576">"<xliff:g id="APP">%1$s</xliff:g> läuft"</string>
<string name="heavy_weight_notification_detail" msgid="6802247239468404078">"Tippe, um zum Spiel zurückzukehren"</string>
<string name="heavy_weight_switcher_title" msgid="3861984210040100886">"Spiel wählen"</string>
@@ -1874,10 +1869,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Von deinem Administrator aktualisiert"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Von deinem Administrator gelöscht"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"Der Energiesparmodus aktiviert das dunkle Design und schränkt Hintergrundaktivitäten, einige Funktionen und optische Effekte und manche Netzwerkverbindungen ein oder deaktiviert sie.\n\n"<annotation id="url">"Weitere Informationen"</annotation></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_enable_title" msgid="7080620065745260137">"Datensparmodus aktivieren?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"Aktivieren"</string>
@@ -1980,10 +1973,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ist momentan nicht verfügbar. Dies wird über die App \"<xliff:g id="APP_NAME_1">%2$s</xliff:g>\" verwaltet."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"Weitere Informationen"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"App-Pausierung aufheben"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"Geschäftliche Apps aktivieren?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"Du erhältst Zugriff auf deine geschäftlichen Apps und Benachrichtigungen"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Aktivieren"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"App ist nicht verfügbar"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ist derzeit nicht verfügbar."</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 1f11664..d3715d3 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -609,14 +609,14 @@
<string-array name="fingerprint_error_vendor">
</string-array>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Εικονίδιο δακτυλικών αποτυπωμάτων"</string>
- <string name="permlab_manageFace" msgid="4569549381889283282">"διαχείριση εξοπλισμού Face Unlock"</string>
+ <string name="permlab_manageFace" msgid="4569549381889283282">"διαχείριση εξοπλισμού για ξεκλείδωμα με το πρόσωπο"</string>
<string name="permdesc_manageFace" msgid="6204569688492710471">"Επιτρέπει στην εφαρμογή να επικαλείται μεθόδους προσθήκης/διαγραφής προτύπων για χρήση."</string>
- <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"χρήση εξοπλισμού Face Unlock"</string>
- <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Επιτρέπει στην εφαρμογή να χρησιμοποιεί εξοπλισμό Face Unlock για έλεγχο ταυτότητας"</string>
- <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Face Unlock"</string>
+ <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"χρήση εξοπλισμού για ξεκλείδωμα με το πρόσωπο"</string>
+ <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Επιτρέπει στην εφαρμογή έλεγχο ταυτότητας με χρήση εξοπλισμού για ξεκλείδωμα με το πρόσωπο"</string>
+ <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Ξεκλείδωμα με το πρόσωπο"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Εγγράψτε ξανά το πρόσωπό σας"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Για να βελτιώσετε την αναγνώριση, εγγράψτε ξανά το πρόσωπό σας"</string>
- <string name="face_setup_notification_title" msgid="550617822603450009">"Ρυθμίστε το Face Unlock"</string>
+ <string name="face_setup_notification_title" msgid="550617822603450009">"Ρυθμίστε το ξεκλείδωμα με το πρόσωπο"</string>
<string name="face_setup_notification_content" msgid="5463999831057751676">"Ξεκλειδώστε το τηλέφωνό σας απλώς κοιτώντας το"</string>
<string name="fingerprint_setup_notification_title" msgid="2002630611398849495">"Ρυθμίστε περισσότερους τρόπους ξεκλειδώματος"</string>
<string name="fingerprint_setup_notification_content" msgid="205578121848324852">"Πατήστε για να προσθέσετε δακτυλικό αποτύπωμα"</string>
@@ -643,18 +643,18 @@
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="5085202213036026288">"Αδύν. επαλήθ. προσώπου. Μη διαθέσιμος εξοπλισμός."</string>
- <string name="face_error_timeout" msgid="522924647742024699">"Δοκιμάστε ξανά το Face Unlock."</string>
+ <string name="face_error_timeout" msgid="522924647742024699">"Δοκιμάστε ξανά για ξεκλείδωμα με το πρόσωπο."</string>
<string name="face_error_no_space" msgid="5649264057026021723">"Η αποθήκ. νέων δεδομ. προσώπ. είναι αδύν. Διαγρ. ένα παλιό."</string>
<string name="face_error_canceled" msgid="2164434737103802131">"Η ενέργεια προσώπου ακυρώθηκε."</string>
- <string name="face_error_user_canceled" msgid="8553045452825849843">"Το Face Unlock ακυρώθηκε από τον χρήστη."</string>
+ <string name="face_error_user_canceled" msgid="8553045452825849843">"Το ξεκλείδωμα με το πρόσωπο ακυρώθηκε από τον χρήστη."</string>
<string name="face_error_lockout" msgid="7864408714994529437">"Πάρα πολλές προσπάθειες. Δοκιμάστε ξανά αργότερα."</string>
- <string name="face_error_lockout_permanent" msgid="8277853602168960343">"Υπερβολικά πολλές προσπάθειες. Το Face Unlock απενεργοποιήθηκε."</string>
+ <string name="face_error_lockout_permanent" msgid="8277853602168960343">"Υπερβολικά πολλές προσπάθειες. Το ξεκλείδωμα με το πρόσωπο απενεργοποιήθηκε."</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"Αδύνατη επαλήθευση του προσώπου. Επανάληψη."</string>
- <string name="face_error_not_enrolled" msgid="7369928733504691611">"Δεν έχετε ρυθμίσει το Face Unlock."</string>
- <string name="face_error_hw_not_present" msgid="1070600921591729944">"Το Face Unlock δεν υποστηρίζεται σε αυτήν τη συσκευή."</string>
+ <string name="face_error_not_enrolled" msgid="7369928733504691611">"Δεν έχετε ρυθμίσει το ξεκλείδωμα με το πρόσωπο."</string>
+ <string name="face_error_hw_not_present" msgid="1070600921591729944">"Το Ξεκλείδωμα με το πρόσωπο δεν υποστηρίζεται σε αυτήν τη συσκευή."</string>
<string name="face_error_security_update_required" msgid="5076017208528750161">"Ο αισθητήρας απενεργοποιήθηκε προσωρινά."</string>
<string name="face_name_template" msgid="3877037340223318119">"Πρόσωπο <xliff:g id="FACEID">%d</xliff:g>"</string>
- <string name="face_app_setting_name" msgid="8130135875458467243">"Χρήση Face Unlock"</string>
+ <string name="face_app_setting_name" msgid="8130135875458467243">"Χρήση ξεκλειδώματος με το πρόσωπο"</string>
<string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"Χρήση προσώπου ή κλειδώματος οθόνης"</string>
<string name="face_dialog_default_subtitle" msgid="6620492813371195429">"Χρησιμοποιήστε το πρόσωπό σας για να συνεχίσετε"</string>
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Χρησιμοποιήστε το πρόσωπό σας ή το κλείδωμα οθόνης για συνέχεια"</string>
@@ -887,7 +887,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Προσπαθήστε ξανά"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"Προσπαθήστε ξανά"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"Ξεκλείδωμα για όλες τις λειτουργίες και δεδομένα"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Έγινε υπέρβαση του μέγιστου αριθμού προσπαθειών Face Unlock"</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Έγινε υπέρβαση του μέγιστου αριθμού προσπαθειών για Ξεκλείδωμα με το πρόσωπο"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"Δεν υπάρχει κάρτα SIM"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"Δεν υπάρχει κάρτα SIM στο tablet."</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"Δεν υπάρχει κάρτα SIM στη συσκευή σας Android TV."</string>
@@ -957,7 +957,7 @@
<string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"Ανάπτυξη περιοχής ξεκλειδώματος."</string>
<string name="keyguard_accessibility_slide_unlock" msgid="2968195219692413046">"Ξεκλείδωμα ολίσθησης."</string>
<string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"Ξεκλείδωμα μοτίβου."</string>
- <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"Face unlock."</string>
+ <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"Ξεκλείδωμα με το πρόσωπο."</string>
<string name="keyguard_accessibility_pin_unlock" msgid="4020864007967340068">"Ξεκλείδωμα κωδικού ασφαλείας"</string>
<string name="keyguard_accessibility_sim_pin_unlock" msgid="4895939120871890557">"Ξεκλείδωμα αριθμού PIN κάρτας SIM."</string>
<string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"Ξεκλείδωμα αριθμού PUK κάρτας SIM."</string>
@@ -1869,10 +1869,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">"OK"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"Η Εξοικονόμηση μπαταρίας ενεργοποιεί το Σκούρο θέμα και περιορίζει ή απενεργοποιεί τη δραστηριότητα στο παρασκήνιο, ορισμένα οπτικά εφέ, συγκεκριμένες λειτουργίες και ορισμένες συνδέσεις δικτύου.\n\n"<annotation id="url">"Μάθετε περισσότερα"</annotation></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>
@@ -1975,10 +1973,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"Η εφαρμογή <xliff:g id="APP_NAME_0">%1$s</xliff:g> δεν είναι διαθέσιμη αυτήν τη στιγμή. Η διαχείριση πραγματοποιείται από την εφαρμογή <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"Μάθετε περισσότερα"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Κατάργηση παύσης εφαρμογής"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"Ενεργοπ. εφαρμογών εργασιών;"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"Αποκτήστε πρόσβαση στις εφαρμογές εργασιών και τις ειδοποιήσεις"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Ενεργοποίηση"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"Η εφαρμογή δεν είναι διαθέσιμη"</string>
<string name="app_blocked_message" msgid="542972921087873023">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> δεν είναι διαθέσιμη αυτήν τη στιγμή."</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 2246e95..953fa17 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -609,14 +609,14 @@
<string-array name="fingerprint_error_vendor">
</string-array>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Fingerprint icon"</string>
- <string name="permlab_manageFace" msgid="4569549381889283282">"manage face unlock hardware"</string>
+ <string name="permlab_manageFace" msgid="4569549381889283282">"manage Face Unlock hardware"</string>
<string name="permdesc_manageFace" msgid="6204569688492710471">"Allows the app to invoke methods to add and delete facial templates for use."</string>
- <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"use face unlock hardware"</string>
- <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Allows the app to use face unlock hardware for authentication"</string>
- <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Face unlock"</string>
+ <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"use Face Unlock hardware"</string>
+ <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Allows the app to use Face Unlock hardware for authentication"</string>
+ <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Face Unlock"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Re-enrol your face"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"To improve recognition, please re-enrol your face"</string>
- <string name="face_setup_notification_title" msgid="550617822603450009">"Set up face unlock"</string>
+ <string name="face_setup_notification_title" msgid="550617822603450009">"Set up Face Unlock"</string>
<string name="face_setup_notification_content" msgid="5463999831057751676">"Unlock your phone by looking at it"</string>
<string name="fingerprint_setup_notification_title" msgid="2002630611398849495">"Set up more ways to unlock"</string>
<string name="fingerprint_setup_notification_content" msgid="205578121848324852">"Tap to add a fingerprint"</string>
@@ -643,18 +643,18 @@
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="5085202213036026288">"Can’t verify face. Hardware not available."</string>
- <string name="face_error_timeout" msgid="522924647742024699">"Try face unlock again."</string>
+ <string name="face_error_timeout" msgid="522924647742024699">"Try Face Unlock again."</string>
<string name="face_error_no_space" msgid="5649264057026021723">"Can’t store new face data. Delete an old one first."</string>
<string name="face_error_canceled" msgid="2164434737103802131">"Face operation cancelled."</string>
- <string name="face_error_user_canceled" msgid="8553045452825849843">"Face unlock cancelled by user."</string>
+ <string name="face_error_user_canceled" msgid="8553045452825849843">"Face Unlock cancelled by user."</string>
<string name="face_error_lockout" msgid="7864408714994529437">"Too many attempts. Try again later."</string>
- <string name="face_error_lockout_permanent" msgid="8277853602168960343">"Too many attempts. Face unlock disabled."</string>
+ <string name="face_error_lockout_permanent" msgid="8277853602168960343">"Too many attempts. Face Unlock disabled."</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"Can’t verify face. Try again."</string>
- <string name="face_error_not_enrolled" msgid="7369928733504691611">"You haven’t set up face unlock."</string>
- <string name="face_error_hw_not_present" msgid="1070600921591729944">"Face unlock is not supported on this device."</string>
+ <string name="face_error_not_enrolled" msgid="7369928733504691611">"You haven’t set up Face Unlock."</string>
+ <string name="face_error_hw_not_present" msgid="1070600921591729944">"Face Unlock is not supported on this device."</string>
<string name="face_error_security_update_required" msgid="5076017208528750161">"Sensor temporarily disabled."</string>
<string name="face_name_template" msgid="3877037340223318119">"Face <xliff:g id="FACEID">%d</xliff:g>"</string>
- <string name="face_app_setting_name" msgid="8130135875458467243">"Use face unlock"</string>
+ <string name="face_app_setting_name" msgid="8130135875458467243">"Use Face Unlock"</string>
<string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"Use face or screen lock"</string>
<string name="face_dialog_default_subtitle" msgid="6620492813371195429">"Use your face to continue"</string>
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Use your face or screen lock to continue"</string>
@@ -887,7 +887,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Try again"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"Try again"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"Unlock for all features and data"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Maximum face unlock attempts exceeded"</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Maximum Face Unlock attempts exceeded"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"No SIM card"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"No SIM card in tablet."</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"No SIM card in your Android TV device."</string>
@@ -957,7 +957,7 @@
<string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"Expand unlock area."</string>
<string name="keyguard_accessibility_slide_unlock" msgid="2968195219692413046">"Slide unlock."</string>
<string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"Pattern unlock."</string>
- <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"Face unlock."</string>
+ <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"Face Unlock."</string>
<string name="keyguard_accessibility_pin_unlock" msgid="4020864007967340068">"Pin unlock."</string>
<string name="keyguard_accessibility_sim_pin_unlock" msgid="4895939120871890557">"SIM PIN unlock."</string>
<string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"SIM PUK unlock."</string>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index 33c6d71..b3b1ff5 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -609,14 +609,14 @@
<string-array name="fingerprint_error_vendor">
</string-array>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Fingerprint icon"</string>
- <string name="permlab_manageFace" msgid="4569549381889283282">"manage face unlock hardware"</string>
+ <string name="permlab_manageFace" msgid="4569549381889283282">"manage Face Unlock hardware"</string>
<string name="permdesc_manageFace" msgid="6204569688492710471">"Allows the app to invoke methods to add and delete facial templates for use."</string>
- <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"use face unlock hardware"</string>
- <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Allows the app to use face unlock hardware for authentication"</string>
- <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Face unlock"</string>
+ <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"use Face Unlock hardware"</string>
+ <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Allows the app to use Face Unlock hardware for authentication"</string>
+ <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Face Unlock"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Re-enrol your face"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"To improve recognition, please re-enrol your face"</string>
- <string name="face_setup_notification_title" msgid="550617822603450009">"Set up face unlock"</string>
+ <string name="face_setup_notification_title" msgid="550617822603450009">"Set up Face Unlock"</string>
<string name="face_setup_notification_content" msgid="5463999831057751676">"Unlock your phone by looking at it"</string>
<string name="fingerprint_setup_notification_title" msgid="2002630611398849495">"Set up more ways to unlock"</string>
<string name="fingerprint_setup_notification_content" msgid="205578121848324852">"Tap to add a fingerprint"</string>
@@ -643,18 +643,18 @@
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="5085202213036026288">"Can’t verify face. Hardware not available."</string>
- <string name="face_error_timeout" msgid="522924647742024699">"Try face unlock again."</string>
+ <string name="face_error_timeout" msgid="522924647742024699">"Try Face Unlock again."</string>
<string name="face_error_no_space" msgid="5649264057026021723">"Can’t store new face data. Delete an old one first."</string>
<string name="face_error_canceled" msgid="2164434737103802131">"Face operation cancelled."</string>
- <string name="face_error_user_canceled" msgid="8553045452825849843">"Face unlock cancelled by user."</string>
+ <string name="face_error_user_canceled" msgid="8553045452825849843">"Face Unlock cancelled by user."</string>
<string name="face_error_lockout" msgid="7864408714994529437">"Too many attempts. Try again later."</string>
- <string name="face_error_lockout_permanent" msgid="8277853602168960343">"Too many attempts. Face unlock disabled."</string>
+ <string name="face_error_lockout_permanent" msgid="8277853602168960343">"Too many attempts. Face Unlock disabled."</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"Can’t verify face. Try again."</string>
- <string name="face_error_not_enrolled" msgid="7369928733504691611">"You haven’t set up face unlock."</string>
- <string name="face_error_hw_not_present" msgid="1070600921591729944">"Face unlock is not supported on this device."</string>
+ <string name="face_error_not_enrolled" msgid="7369928733504691611">"You haven’t set up Face Unlock."</string>
+ <string name="face_error_hw_not_present" msgid="1070600921591729944">"Face Unlock is not supported on this device."</string>
<string name="face_error_security_update_required" msgid="5076017208528750161">"Sensor temporarily disabled."</string>
<string name="face_name_template" msgid="3877037340223318119">"Face <xliff:g id="FACEID">%d</xliff:g>"</string>
- <string name="face_app_setting_name" msgid="8130135875458467243">"Use face unlock"</string>
+ <string name="face_app_setting_name" msgid="8130135875458467243">"Use Face Unlock"</string>
<string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"Use face or screen lock"</string>
<string name="face_dialog_default_subtitle" msgid="6620492813371195429">"Use your face to continue"</string>
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Use your face or screen lock to continue"</string>
@@ -887,7 +887,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Try again"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"Try again"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"Unlock for all features and data"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Maximum face unlock attempts exceeded"</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Maximum Face Unlock attempts exceeded"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"No SIM card"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"No SIM card in tablet."</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"No SIM card in your Android TV device."</string>
@@ -957,7 +957,7 @@
<string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"Expand unlock area."</string>
<string name="keyguard_accessibility_slide_unlock" msgid="2968195219692413046">"Slide unlock."</string>
<string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"Pattern unlock."</string>
- <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"Face unlock."</string>
+ <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"Face Unlock."</string>
<string name="keyguard_accessibility_pin_unlock" msgid="4020864007967340068">"Pin unlock."</string>
<string name="keyguard_accessibility_sim_pin_unlock" msgid="4895939120871890557">"SIM PIN unlock."</string>
<string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"SIM PUK unlock."</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index a08ad1d..0c60a02 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -609,14 +609,14 @@
<string-array name="fingerprint_error_vendor">
</string-array>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Fingerprint icon"</string>
- <string name="permlab_manageFace" msgid="4569549381889283282">"manage face unlock hardware"</string>
+ <string name="permlab_manageFace" msgid="4569549381889283282">"manage Face Unlock hardware"</string>
<string name="permdesc_manageFace" msgid="6204569688492710471">"Allows the app to invoke methods to add and delete facial templates for use."</string>
- <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"use face unlock hardware"</string>
- <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Allows the app to use face unlock hardware for authentication"</string>
- <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Face unlock"</string>
+ <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"use Face Unlock hardware"</string>
+ <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Allows the app to use Face Unlock hardware for authentication"</string>
+ <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Face Unlock"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Re-enrol your face"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"To improve recognition, please re-enrol your face"</string>
- <string name="face_setup_notification_title" msgid="550617822603450009">"Set up face unlock"</string>
+ <string name="face_setup_notification_title" msgid="550617822603450009">"Set up Face Unlock"</string>
<string name="face_setup_notification_content" msgid="5463999831057751676">"Unlock your phone by looking at it"</string>
<string name="fingerprint_setup_notification_title" msgid="2002630611398849495">"Set up more ways to unlock"</string>
<string name="fingerprint_setup_notification_content" msgid="205578121848324852">"Tap to add a fingerprint"</string>
@@ -643,18 +643,18 @@
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="5085202213036026288">"Can’t verify face. Hardware not available."</string>
- <string name="face_error_timeout" msgid="522924647742024699">"Try face unlock again."</string>
+ <string name="face_error_timeout" msgid="522924647742024699">"Try Face Unlock again."</string>
<string name="face_error_no_space" msgid="5649264057026021723">"Can’t store new face data. Delete an old one first."</string>
<string name="face_error_canceled" msgid="2164434737103802131">"Face operation cancelled."</string>
- <string name="face_error_user_canceled" msgid="8553045452825849843">"Face unlock cancelled by user."</string>
+ <string name="face_error_user_canceled" msgid="8553045452825849843">"Face Unlock cancelled by user."</string>
<string name="face_error_lockout" msgid="7864408714994529437">"Too many attempts. Try again later."</string>
- <string name="face_error_lockout_permanent" msgid="8277853602168960343">"Too many attempts. Face unlock disabled."</string>
+ <string name="face_error_lockout_permanent" msgid="8277853602168960343">"Too many attempts. Face Unlock disabled."</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"Can’t verify face. Try again."</string>
- <string name="face_error_not_enrolled" msgid="7369928733504691611">"You haven’t set up face unlock."</string>
- <string name="face_error_hw_not_present" msgid="1070600921591729944">"Face unlock is not supported on this device."</string>
+ <string name="face_error_not_enrolled" msgid="7369928733504691611">"You haven’t set up Face Unlock."</string>
+ <string name="face_error_hw_not_present" msgid="1070600921591729944">"Face Unlock is not supported on this device."</string>
<string name="face_error_security_update_required" msgid="5076017208528750161">"Sensor temporarily disabled."</string>
<string name="face_name_template" msgid="3877037340223318119">"Face <xliff:g id="FACEID">%d</xliff:g>"</string>
- <string name="face_app_setting_name" msgid="8130135875458467243">"Use face unlock"</string>
+ <string name="face_app_setting_name" msgid="8130135875458467243">"Use Face Unlock"</string>
<string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"Use face or screen lock"</string>
<string name="face_dialog_default_subtitle" msgid="6620492813371195429">"Use your face to continue"</string>
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Use your face or screen lock to continue"</string>
@@ -887,7 +887,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Try again"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"Try again"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"Unlock for all features and data"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Maximum face unlock attempts exceeded"</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Maximum Face Unlock attempts exceeded"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"No SIM card"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"No SIM card in tablet."</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"No SIM card in your Android TV device."</string>
@@ -957,7 +957,7 @@
<string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"Expand unlock area."</string>
<string name="keyguard_accessibility_slide_unlock" msgid="2968195219692413046">"Slide unlock."</string>
<string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"Pattern unlock."</string>
- <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"Face unlock."</string>
+ <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"Face Unlock."</string>
<string name="keyguard_accessibility_pin_unlock" msgid="4020864007967340068">"Pin unlock."</string>
<string name="keyguard_accessibility_sim_pin_unlock" msgid="4895939120871890557">"SIM PIN unlock."</string>
<string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"SIM PUK unlock."</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 44eba89..3830047 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -609,14 +609,14 @@
<string-array name="fingerprint_error_vendor">
</string-array>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Fingerprint icon"</string>
- <string name="permlab_manageFace" msgid="4569549381889283282">"manage face unlock hardware"</string>
+ <string name="permlab_manageFace" msgid="4569549381889283282">"manage Face Unlock hardware"</string>
<string name="permdesc_manageFace" msgid="6204569688492710471">"Allows the app to invoke methods to add and delete facial templates for use."</string>
- <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"use face unlock hardware"</string>
- <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Allows the app to use face unlock hardware for authentication"</string>
- <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Face unlock"</string>
+ <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"use Face Unlock hardware"</string>
+ <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Allows the app to use Face Unlock hardware for authentication"</string>
+ <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Face Unlock"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Re-enrol your face"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"To improve recognition, please re-enrol your face"</string>
- <string name="face_setup_notification_title" msgid="550617822603450009">"Set up face unlock"</string>
+ <string name="face_setup_notification_title" msgid="550617822603450009">"Set up Face Unlock"</string>
<string name="face_setup_notification_content" msgid="5463999831057751676">"Unlock your phone by looking at it"</string>
<string name="fingerprint_setup_notification_title" msgid="2002630611398849495">"Set up more ways to unlock"</string>
<string name="fingerprint_setup_notification_content" msgid="205578121848324852">"Tap to add a fingerprint"</string>
@@ -643,18 +643,18 @@
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="5085202213036026288">"Can’t verify face. Hardware not available."</string>
- <string name="face_error_timeout" msgid="522924647742024699">"Try face unlock again."</string>
+ <string name="face_error_timeout" msgid="522924647742024699">"Try Face Unlock again."</string>
<string name="face_error_no_space" msgid="5649264057026021723">"Can’t store new face data. Delete an old one first."</string>
<string name="face_error_canceled" msgid="2164434737103802131">"Face operation cancelled."</string>
- <string name="face_error_user_canceled" msgid="8553045452825849843">"Face unlock cancelled by user."</string>
+ <string name="face_error_user_canceled" msgid="8553045452825849843">"Face Unlock cancelled by user."</string>
<string name="face_error_lockout" msgid="7864408714994529437">"Too many attempts. Try again later."</string>
- <string name="face_error_lockout_permanent" msgid="8277853602168960343">"Too many attempts. Face unlock disabled."</string>
+ <string name="face_error_lockout_permanent" msgid="8277853602168960343">"Too many attempts. Face Unlock disabled."</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"Can’t verify face. Try again."</string>
- <string name="face_error_not_enrolled" msgid="7369928733504691611">"You haven’t set up face unlock."</string>
- <string name="face_error_hw_not_present" msgid="1070600921591729944">"Face unlock is not supported on this device."</string>
+ <string name="face_error_not_enrolled" msgid="7369928733504691611">"You haven’t set up Face Unlock."</string>
+ <string name="face_error_hw_not_present" msgid="1070600921591729944">"Face Unlock is not supported on this device."</string>
<string name="face_error_security_update_required" msgid="5076017208528750161">"Sensor temporarily disabled."</string>
<string name="face_name_template" msgid="3877037340223318119">"Face <xliff:g id="FACEID">%d</xliff:g>"</string>
- <string name="face_app_setting_name" msgid="8130135875458467243">"Use face unlock"</string>
+ <string name="face_app_setting_name" msgid="8130135875458467243">"Use Face Unlock"</string>
<string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"Use face or screen lock"</string>
<string name="face_dialog_default_subtitle" msgid="6620492813371195429">"Use your face to continue"</string>
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Use your face or screen lock to continue"</string>
@@ -887,7 +887,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Try again"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"Try again"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"Unlock for all features and data"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Maximum face unlock attempts exceeded"</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Maximum Face Unlock attempts exceeded"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"No SIM card"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"No SIM card in tablet."</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"No SIM card in your Android TV device."</string>
@@ -957,7 +957,7 @@
<string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"Expand unlock area."</string>
<string name="keyguard_accessibility_slide_unlock" msgid="2968195219692413046">"Slide unlock."</string>
<string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"Pattern unlock."</string>
- <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"Face unlock."</string>
+ <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"Face Unlock."</string>
<string name="keyguard_accessibility_pin_unlock" msgid="4020864007967340068">"Pin unlock."</string>
<string name="keyguard_accessibility_sim_pin_unlock" msgid="4895939120871890557">"SIM PIN unlock."</string>
<string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"SIM PUK unlock."</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 624a678..15b1ec8 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -655,7 +655,7 @@
<string name="face_error_security_update_required" msgid="5076017208528750161">"Se inhabilitó temporalmente el sensor."</string>
<string name="face_name_template" msgid="3877037340223318119">"Rostro <xliff:g id="FACEID">%d</xliff:g>"</string>
<string name="face_app_setting_name" msgid="8130135875458467243">"Usar desbloqueo facial"</string>
- <string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"Usar bloqueo facial o de pantalla"</string>
+ <string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"Usar desbloqueo facial o de pantalla"</string>
<string name="face_dialog_default_subtitle" msgid="6620492813371195429">"Usa el rostro para continuar"</string>
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Usa tu rostro o bloqueo de pantalla para continuar"</string>
<string-array name="face_error_vendor">
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 00a7522..5b147b4 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -609,14 +609,14 @@
<string-array name="fingerprint_error_vendor">
</string-array>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Icono de huella digital"</string>
- <string name="permlab_manageFace" msgid="4569549381889283282">"gestionar el hardware de desbloqueo facial"</string>
+ <string name="permlab_manageFace" msgid="4569549381889283282">"gestionar el hardware de Desbloqueo facial"</string>
<string name="permdesc_manageFace" msgid="6204569688492710471">"Permite que la app use métodos para añadir y suprimir plantillas de caras para su uso."</string>
- <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"Utilizar hardware de desbloqueo facial"</string>
- <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Permite que la aplicación utilice el hardware de desbloqueo facial para autenticarte"</string>
+ <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"utilizar hardware de Desbloqueo facial"</string>
+ <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Permite que la aplicación utilice el hardware de Desbloqueo facial para autenticarte"</string>
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Desbloqueo facial"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Volver a registrar la cara"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Para mejorar el reconocimiento, vuelve a registrar tu cara"</string>
- <string name="face_setup_notification_title" msgid="550617822603450009">"Configura el desbloqueo facial"</string>
+ <string name="face_setup_notification_title" msgid="550617822603450009">"Configura Desbloqueo facial"</string>
<string name="face_setup_notification_content" msgid="5463999831057751676">"Desbloquea el teléfono con solo mirarlo"</string>
<string name="fingerprint_setup_notification_title" msgid="2002630611398849495">"Configura más formas de desbloqueo"</string>
<string name="fingerprint_setup_notification_content" msgid="205578121848324852">"Toca para añadir una huella digital"</string>
@@ -643,19 +643,19 @@
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="5085202213036026288">"No se puede verificar. Hardware no disponible."</string>
- <string name="face_error_timeout" msgid="522924647742024699">"Vuelve a probar el desbloqueo facial."</string>
+ <string name="face_error_timeout" msgid="522924647742024699">"Vuelve a probar Desbloqueo facial."</string>
<string name="face_error_no_space" msgid="5649264057026021723">"Para guardar nuevos datos faciales, borra otros antiguos."</string>
<string name="face_error_canceled" msgid="2164434737103802131">"Se ha cancelado el reconocimiento facial."</string>
- <string name="face_error_user_canceled" msgid="8553045452825849843">"El usuario ha cancelado el desbloqueo facial."</string>
+ <string name="face_error_user_canceled" msgid="8553045452825849843">"El usuario ha cancelado Desbloqueo facial."</string>
<string name="face_error_lockout" msgid="7864408714994529437">"Demasiados intentos. Inténtalo de nuevo más tarde."</string>
- <string name="face_error_lockout_permanent" msgid="8277853602168960343">"Muchos intentos. Se ha inhabilitado el desbloqueo facial."</string>
+ <string name="face_error_lockout_permanent" msgid="8277853602168960343">"Muchos intentos. Se ha inhabilitado Desbloqueo facial."</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"No se ha verificado tu cara. Vuelve a intentarlo."</string>
- <string name="face_error_not_enrolled" msgid="7369928733504691611">"No has configurado el desbloqueo facial."</string>
- <string name="face_error_hw_not_present" msgid="1070600921591729944">"El desbloqueo facial no está disponible en este dispositivo."</string>
+ <string name="face_error_not_enrolled" msgid="7369928733504691611">"No has configurado Desbloqueo facial."</string>
+ <string name="face_error_hw_not_present" msgid="1070600921591729944">"Desbloqueo facial no está disponible en este dispositivo."</string>
<string name="face_error_security_update_required" msgid="5076017208528750161">"El sensor está inhabilitado en estos momentos."</string>
<string name="face_name_template" msgid="3877037340223318119">"Cara <xliff:g id="FACEID">%d</xliff:g>"</string>
- <string name="face_app_setting_name" msgid="8130135875458467243">"Usar desbloqueo facial"</string>
- <string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"Usar desbloqueo facial o bloqueo de pantalla"</string>
+ <string name="face_app_setting_name" msgid="8130135875458467243">"Usar Desbloqueo facial"</string>
+ <string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"Usar Desbloqueo facial o Bloqueo de pantalla"</string>
<string name="face_dialog_default_subtitle" msgid="6620492813371195429">"Usa tu cara para continuar"</string>
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Usa tu cara o tu bloqueo de pantalla para continuar"</string>
<string-array name="face_error_vendor">
@@ -887,7 +887,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Vuelve a intentarlo"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"Vuelve a intentarlo"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"Desbloquear para todos los datos y funciones"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Se ha superado el número máximo de intentos de desbloqueo facial."</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Se ha superado el número máximo de intentos de Desbloqueo facial."</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"Falta la tarjeta SIM."</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"No se ha insertado ninguna tarjeta SIM en el tablet."</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"No hay ninguna tarjeta SIM en tu dispositivo Android TV."</string>
@@ -1271,12 +1271,12 @@
<string name="new_app_action" msgid="547772182913269801">"Abrir <xliff:g id="NEW_APP">%1$s</xliff:g>"</string>
<string name="new_app_description" msgid="1958903080400806644">"<xliff:g id="OLD_APP">%1$s</xliff:g> se cerrará sin guardar"</string>
<string name="dump_heap_notification" msgid="5316644945404825032">"<xliff:g id="PROC">%1$s</xliff:g> ha superado el límite de memoria"</string>
- <string name="dump_heap_ready_notification" msgid="2302452262927390268">"El volcado de pila <xliff:g id="PROC">%1$s</xliff:g> está listo"</string>
- <string name="dump_heap_notification_detail" msgid="8431586843001054050">"Se ha recopilado un volcado de pila. Toca para compartir."</string>
- <string name="dump_heap_title" msgid="4367128917229233901">"¿Compartir volcado de pila?"</string>
- <string name="dump_heap_text" msgid="1692649033835719336">"El proceso <xliff:g id="PROC">%1$s</xliff:g> ha superado su límite de memoria de <xliff:g id="SIZE">%2$s</xliff:g>. Hay un volcado de pila disponible que puedes compartir con su desarrollador (ten cuidado, ya que puede incluir información personal a la que tenga acceso la aplicación)."</string>
- <string name="dump_heap_system_text" msgid="6805155514925350849">"El proceso <xliff:g id="PROC">%1$s</xliff:g> ha superado su límite de memoria de <xliff:g id="SIZE">%2$s</xliff:g>. Hay un volcado de pila disponible que puedes compartir. Ten cuidado, ya que puede incluir información personal sensible a la que el proceso puede acceder, como texto que hayas introducido."</string>
- <string name="dump_heap_ready_text" msgid="5849618132123045516">"Hay un volcado de pila del proceso <xliff:g id="PROC">%1$s</xliff:g> que puedes compartir. Ten cuidado, ya que puede incluir información personal sensible a la que el proceso puede acceder, como texto que hayas introducido."</string>
+ <string name="dump_heap_ready_notification" msgid="2302452262927390268">"El volcado de montículo <xliff:g id="PROC">%1$s</xliff:g> está listo"</string>
+ <string name="dump_heap_notification_detail" msgid="8431586843001054050">"Se ha recopilado un volcado de montículo. Toca para compartir."</string>
+ <string name="dump_heap_title" msgid="4367128917229233901">"¿Compartir volcado de montículo?"</string>
+ <string name="dump_heap_text" msgid="1692649033835719336">"El proceso <xliff:g id="PROC">%1$s</xliff:g> ha superado su límite de memoria de <xliff:g id="SIZE">%2$s</xliff:g>. Hay un volcado de montículo disponible que puedes compartir con su desarrollador (ten cuidado, ya que puede incluir información personal a la que tenga acceso la aplicación)."</string>
+ <string name="dump_heap_system_text" msgid="6805155514925350849">"El proceso <xliff:g id="PROC">%1$s</xliff:g> ha superado su límite de memoria de <xliff:g id="SIZE">%2$s</xliff:g>. Hay un volcado de montículo disponible que puedes compartir. Ten cuidado, ya que puede incluir información personal sensible a la que el proceso puede acceder, como texto que hayas introducido."</string>
+ <string name="dump_heap_ready_text" msgid="5849618132123045516">"Hay un volcado de montículo del proceso <xliff:g id="PROC">%1$s</xliff:g> que puedes compartir. Ten cuidado, ya que puede incluir información personal sensible a la que el proceso puede acceder, como texto que hayas introducido."</string>
<string name="sendText" msgid="493003724401350724">"Selecciona una acción para el texto"</string>
<string name="volume_ringtone" msgid="134784084629229029">"Volumen del timbre"</string>
<string name="volume_music" msgid="7727274216734955095">"Volumen de multimedia"</string>
@@ -1869,10 +1869,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Actualizado por el administrador"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Eliminado por el administrador"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"Aceptar"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"El modo Ahorro de batería activa el tema oscuro y limita o desactiva la actividad en segundo plano, algunos efectos visuales, ciertas funciones y algunas conexiones de red.\n\n"<annotation id="url">"Más información"</annotation></string>
+ <string name="battery_saver_description" msgid="8518809702138617167">"El modo Ahorro de batería activa el tema oscuro y limita o desactiva la actividad en segundo plano, algunos efectos visuales, ciertas funciones y algunas conexiones de red."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Ahorro de datos evita que algunas aplicaciones envíen o reciban datos en segundo plano, lo que puede reducir el uso de datos. Una aplicación que estés usando de forma activa puede acceder a los datos, aunque con menos frecuencia. Esto significa que es posible que, por ejemplo, algunas imágenes no se muestren hasta que las toques."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"¿Activar Ahorro de datos?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"Activar"</string>
@@ -1975,10 +1973,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> no está disponible en este momento. Esta opción se administra en <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"Más información"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Anular pausa de aplicación"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"¿Activar apps de trabajo?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"Accede a tus aplicaciones y notificaciones de trabajo"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Activar"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"La aplicación no está disponible"</string>
<string name="app_blocked_message" msgid="542972921087873023">"En estos momentos, <xliff:g id="APP_NAME">%1$s</xliff:g> no está disponible."</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index dc56e12..d74cca6 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -609,14 +609,14 @@
<string-array name="fingerprint_error_vendor">
</string-array>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Sõrmejälje ikoon"</string>
- <string name="permlab_manageFace" msgid="4569549381889283282">"hallata Face Unlocki riistvara"</string>
+ <string name="permlab_manageFace" msgid="4569549381889283282">"hallata näoga avamise riistvara"</string>
<string name="permdesc_manageFace" msgid="6204569688492710471">"Lubab rakendusel tühistada meetodid kasutatavate näomallide lisamiseks ja kustutamiseks."</string>
- <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"kasutada Face Unlocki riistvara"</string>
- <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Võimaldab rakendusel autentimiseks kasutada Face Unlocki riistvara"</string>
- <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Face Unlock"</string>
+ <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"kasutada näoga avamise riistvara"</string>
+ <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Võimaldab rakendusel autentimiseks kasutada näoga avamise riistvara"</string>
+ <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Näoga avamine"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Registreerige oma nägu uuesti"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Tuvastamise parandamiseks registreerige oma nägu uuesti"</string>
- <string name="face_setup_notification_title" msgid="550617822603450009">"Seadistage Face Unlock"</string>
+ <string name="face_setup_notification_title" msgid="550617822603450009">"Seadistage näoga avamine"</string>
<string name="face_setup_notification_content" msgid="5463999831057751676">"Avage telefon seda vaadates"</string>
<string name="fingerprint_setup_notification_title" msgid="2002630611398849495">"Seadistage rohkem viise avamiseks"</string>
<string name="fingerprint_setup_notification_content" msgid="205578121848324852">"Puudutage sõrmejälje lisamiseks"</string>
@@ -643,19 +643,19 @@
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="5085202213036026288">"Nägu ei saa kinnitada. Riistvara pole saadaval."</string>
- <string name="face_error_timeout" msgid="522924647742024699">"Proovige Face Unlocki uuesti."</string>
+ <string name="face_error_timeout" msgid="522924647742024699">"Proovige näoga avamist uuesti."</string>
<string name="face_error_no_space" msgid="5649264057026021723">"Uue näo andmeid ei saa salvestada. Kustutage enne vanad."</string>
<string name="face_error_canceled" msgid="2164434737103802131">"Näotuvastuse toiming tühistati."</string>
- <string name="face_error_user_canceled" msgid="8553045452825849843">"Kasutaja tühistas Face Unlocki."</string>
+ <string name="face_error_user_canceled" msgid="8553045452825849843">"Kasutaja tühistas näoga avamise."</string>
<string name="face_error_lockout" msgid="7864408714994529437">"Liiga palju katseid. Proovige hiljem uuesti."</string>
- <string name="face_error_lockout_permanent" msgid="8277853602168960343">"Liiga palju katseid. Face Unlock on keelatud."</string>
+ <string name="face_error_lockout_permanent" msgid="8277853602168960343">"Liiga palju katseid. Näoga avamine on keelatud."</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"Nägu ei saa kinnitada. Proovige uuesti."</string>
- <string name="face_error_not_enrolled" msgid="7369928733504691611">"Face Unlocki ei ole seadistatud."</string>
- <string name="face_error_hw_not_present" msgid="1070600921591729944">"Seade ei toeta Face Unlocki."</string>
+ <string name="face_error_not_enrolled" msgid="7369928733504691611">"Näoga avamine ei ole seadistatud."</string>
+ <string name="face_error_hw_not_present" msgid="1070600921591729944">"Seade ei toeta näoga avamist."</string>
<string name="face_error_security_update_required" msgid="5076017208528750161">"Andur on ajutiselt keelatud."</string>
<string name="face_name_template" msgid="3877037340223318119">"Nägu <xliff:g id="FACEID">%d</xliff:g>"</string>
- <string name="face_app_setting_name" msgid="8130135875458467243">"Face Unlocki kasutamine"</string>
- <string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"Face Unlocki või ekraaniluku kasutamine"</string>
+ <string name="face_app_setting_name" msgid="8130135875458467243">"Näoga avamise kasutamine"</string>
+ <string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"Näoga avamise või ekraaniluku kasutamine"</string>
<string name="face_dialog_default_subtitle" msgid="6620492813371195429">"Jätkamiseks kasutage oma nägu"</string>
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Jätkamiseks kasutage oma nägu või ekraanilukku"</string>
<string-array name="face_error_vendor">
@@ -887,7 +887,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Proovige uuesti"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"Proovige uuesti"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"Ava kõigi funktsioonide ja andmete nägemiseks"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Maksimaalne teenusega Face Unlock avamise katsete arv on ületatud"</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Maksimaalne näoga avamise katsete arv on ületatud"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"SIM-kaarti pole"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"Tahvelarvutis pole SIM-kaarti."</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"Teie Android TV seadmes pole SIM-kaarti."</string>
@@ -1022,8 +1022,7 @@
<string name="text_copied" msgid="2531420577879738860">"Lõikelauale kopeeritud tekst."</string>
<string name="copied" msgid="4675902854553014676">"Kopeeritud"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> kleepis rakendusest <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>"</string>
- <!-- no translation found for pasted_from_clipboard (7355790625710831847) -->
- <skip />
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> kleepis teie lõikelaualt"</string>
<string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> kleepis teie kopeeritud teksti"</string>
<string name="pasted_image" msgid="4729097394781491022">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> kleepis teie kopeeritud pildi"</string>
<string name="pasted_content" msgid="646276353060777131">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> kleepis teie kopeeritud sisu"</string>
@@ -1260,14 +1259,10 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Rakenduse <xliff:g id="APPNAME">%1$s</xliff:g> ettevalmistamine."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Rakenduste käivitamine."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Käivitamise lõpuleviimine."</string>
- <!-- no translation found for fp_enrollment_powerbutton_intent_title (3385634173366119903) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_message (6582149052513682522) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_positive_button (5963520983910436791) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_negative_button (6465764183480190748) -->
- <skip />
+ <string name="fp_enrollment_powerbutton_intent_title" msgid="3385634173366119903">"Kas lülitada ekraan välja?"</string>
+ <string name="fp_enrollment_powerbutton_intent_message" msgid="6582149052513682522">"Sõrmejälje seadistamisel vajutasite toitenuppu.\n\nSee lülitab ekraanikuva tavaliselt välja."</string>
+ <string name="fp_enrollment_powerbutton_intent_positive_button" msgid="5963520983910436791">"Lülita välja"</string>
+ <string name="fp_enrollment_powerbutton_intent_negative_button" msgid="6465764183480190748">"Tühista"</string>
<string name="heavy_weight_notification" msgid="8382784283600329576">"<xliff:g id="APP">%1$s</xliff:g> töötab"</string>
<string name="heavy_weight_notification_detail" msgid="6802247239468404078">"Puudutage mängu naasmiseks"</string>
<string name="heavy_weight_switcher_title" msgid="3861984210040100886">"Valige mäng"</string>
@@ -1718,8 +1713,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Kasuta otseteed"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Värvide ümberpööramine"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Värvide korrigeerimine"</string>
- <!-- no translation found for one_handed_mode_feature_name (2334330034828094891) -->
- <skip />
+ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Ühekäerežiim"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Eriti tume"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Helitugevuse klahve hoiti all. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> lülitati sisse."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Helitugevuse klahve hoiti all. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> lülitati välja."</string>
@@ -1875,10 +1869,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Administraator on seda värskendanud"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Administraator on selle kustutanud"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"Akusäästja lülitab sisse tumeda teema ja lülitab välja taustategevused, mõned visuaalsed efektid, teatud funktsioonid ja võrguühendused või piirab neid.\n\n"<annotation id="url">"Lisateave"</annotation></string>
+ <string name="battery_saver_description" msgid="8518809702138617167">"Akusäästja lülitab sisse tumeda teema ja lülitab välja taustategevused, mõned visuaalsed efektid, teatud funktsioonid ja võrguühendused või piirab neid."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Andmekasutuse vähendamiseks keelab andmemahu säästja mõne rakenduse puhul andmete taustal saatmise ja vastuvõtmise. Rakendus, mida praegu kasutate, pääseb andmesidele juurde, kuid võib seda teha väiksema sagedusega. Seetõttu võidakse näiteks pildid kuvada alles siis, kui neid puudutate."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Lülitada andmemahu säästja sisse?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"Lülita sisse"</string>
@@ -1981,10 +1973,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> pole praegu saadaval. Seda haldab rakendus <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"Lisateave"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Jätka rakendust"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"Lülitada töörakendused sisse?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"Hankige juurdepääs oma töörakendustele ja märguannetele"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Lülita sisse"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"Rakendus ei ole saadaval"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ei ole praegu saadaval."</string>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 428832d..06e73b1 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -42,7 +42,7 @@
<string name="serviceErased" msgid="997354043770513494">"Behar bezala ezabatu da."</string>
<string name="passwordIncorrect" msgid="917087532676155877">"Pasahitz okerra."</string>
<string name="mmiComplete" msgid="6341884570892520140">"MMI osatu da."</string>
- <string name="badPin" msgid="888372071306274355">"Idatzi duzun PIN kode zaharra ez da zuzena."</string>
+ <string name="badPin" msgid="888372071306274355">"Idatzi duzun PIN zaharra ez da zuzena."</string>
<string name="badPuk" msgid="4232069163733147376">"Idatzi duzun PUK kode zaharra ez da zuzena. Saiatu berriro."</string>
<string name="mismatchPin" msgid="2929611853228707473">"Idatzi dituzun PIN kodeak ez datoz bat."</string>
<string name="invalidPin" msgid="7542498253319440408">"Idatzi 4 eta 8 zenbaki bitarteko PIN bat."</string>
@@ -906,7 +906,7 @@
<string name="emergency_calls_only" msgid="3057351206678279851">"Larrialdi-deiak soilik"</string>
<string name="lockscreen_network_locked_message" msgid="2814046965899249635">"Sarea blokeatuta dago"</string>
<string name="lockscreen_sim_puk_locked_message" msgid="6618356415831082174">"SIM txartela PUK bidez blokeatuta dago."</string>
- <string name="lockscreen_sim_puk_locked_instructions" msgid="5307979043730860995">"Ikusi erabiltzailearen gida edo jarri bezeroarentzako laguntza-zerbitzuarekin harremanetan."</string>
+ <string name="lockscreen_sim_puk_locked_instructions" msgid="5307979043730860995">"Ikusi erabiltzailearentzako gida edo jarri bezeroarentzako laguntza-zerbitzuarekin harremanetan."</string>
<string name="lockscreen_sim_locked_message" msgid="3160196135801185938">"SIM txartela blokeatuta dago."</string>
<string name="lockscreen_sim_unlock_progress_dialog_message" msgid="2286497117428409709">"SIM txartela desblokeatzen…"</string>
<string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6458790975898594240">"Desblokeatzeko eredua oker marraztu duzu <xliff:g id="NUMBER_0">%1$d</xliff:g> aldiz. \n\nSaiatu berriro <xliff:g id="NUMBER_1">%2$d</xliff:g> segundo barru."</string>
@@ -1869,10 +1869,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Administratzaileak eguneratu du"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Administratzaileak ezabatu du"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"Ados"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"Bateria-aurrezleak gai iluna aktibatzen du, eta murriztu edo desaktibatu egiten ditu atzeko planoko jarduerak, zenbait efektu bisual, eta eginbide jakin eta sareko konexio batzuk.\n\n"<annotation id="url">"Lortu informazio gehiago"</annotation></string>
+ <string name="battery_saver_description" msgid="8518809702138617167">"Bateria-aurrezleak gai iluna aktibatzen du, eta murriztu edo desaktibatu egiten ditu atzeko planoko jarduerak, zenbait efektu bisual, eta eginbide jakin eta sareko konexio batzuk."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Datuen erabilera murrizteko, atzeko planoan datuak bidaltzea eta jasotzea galarazten die datu-aurrezleak aplikazio batzuei. Une honetan erabiltzen ari zaren aplikazio batek datuak atzitu ahal izango ditu, baina baliteke maiztasun txikiagoarekin atzitzea. Horrela, adibidez, baliteke irudiak ez erakustea haiek sakatu arte."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Datu-aurrezlea aktibatu nahi duzu?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"Aktibatu"</string>
@@ -1975,10 +1973,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ez dago erabilgarri une honetan. Haren erabilgarritasuna <xliff:g id="APP_NAME_1">%2$s</xliff:g> aplikazioak kudeatzen du."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"Lortu informazio gehiago"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Kendu pausaldia"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"Laneko aplikazioak aktibatu nahi dituzu?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"Atzitu laneko aplikazioak eta jakinarazpenak"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Aktibatu"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"Aplikazioa ez dago erabilgarri"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ez dago erabilgarri une honetan."</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index b66ad5a..a74b62a 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -609,14 +609,14 @@
<string-array name="fingerprint_error_vendor">
</string-array>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"نماد اثر انگشت"</string>
- <string name="permlab_manageFace" msgid="4569549381889283282">"مدیریت سختافزار «بازگشایی با چهره»"</string>
+ <string name="permlab_manageFace" msgid="4569549381889283282">"مدیریت سختافزار «قفلگشایی با چهره»"</string>
<string name="permdesc_manageFace" msgid="6204569688492710471">"به برنامه امکان میدهد روشهایی را برای افزودن و حذف الگوهای چهره جهت استفاده فرابخواند."</string>
- <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"استفاده از سختافزار «بازگشایی با چهره»"</string>
- <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"به برنامه امکان میدهد از سختافزار «بازگشایی با چهره» برای اصالتسنجی استفاده کند"</string>
- <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"بازگشایی با چهره"</string>
+ <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"استفاده از سختافزار «قفلگشایی با چهره»"</string>
+ <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"به برنامه امکان میدهد از سختافزار «قفلگشایی با چهره» برای اصالتسنجی استفاده کند"</string>
+ <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"قفلگشایی با چهره"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"ثبت مجدد چهره"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"برای بهبود تشخیص، لطفاً چهرهتان را دوباره ثبت کنید"</string>
- <string name="face_setup_notification_title" msgid="550617822603450009">"راهاندازی «بازگشایی با چهره»"</string>
+ <string name="face_setup_notification_title" msgid="550617822603450009">"راهاندازی «قفلگشایی با چهره»"</string>
<string name="face_setup_notification_content" msgid="5463999831057751676">"برای باز کردن قفل تلفن خود به آن نگاه کنید"</string>
<string name="fingerprint_setup_notification_title" msgid="2002630611398849495">"راهاندازی روشهای بیشتر برای باز کردن قفل"</string>
<string name="fingerprint_setup_notification_content" msgid="205578121848324852">"برای افزودن اثر انگشت، ضربه بزنید"</string>
@@ -643,18 +643,18 @@
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="5085202213036026288">"چهره تأیید نشد. سختافزار در دسترس نیست."</string>
- <string name="face_error_timeout" msgid="522924647742024699">"«بازگشایی با چهره» را دوباره امتحان کنید."</string>
+ <string name="face_error_timeout" msgid="522924647742024699">"«قفلگشایی با چهره» را دوباره امتحان کنید."</string>
<string name="face_error_no_space" msgid="5649264057026021723">"داده چهره جدید ذخیره نشد. اول داده چهره قدیمی را حذف کنید."</string>
<string name="face_error_canceled" msgid="2164434737103802131">"عملیات شناسایی چهره لغو شد."</string>
- <string name="face_error_user_canceled" msgid="8553045452825849843">"کاربر «بازگشایی با چهره» را لغو کرد."</string>
+ <string name="face_error_user_canceled" msgid="8553045452825849843">"کاربر «قفلگشایی با چهره» را لغو کرد."</string>
<string name="face_error_lockout" msgid="7864408714994529437">"تعداد زیادی تلاش ناموفق. بعداً دوباره امتحان کنید."</string>
- <string name="face_error_lockout_permanent" msgid="8277853602168960343">"تعداد تلاشها بیشازحد مجاز است. «بازگشایی با چهره» غیرفعال است."</string>
+ <string name="face_error_lockout_permanent" msgid="8277853602168960343">"تعداد تلاشها بیشازحد مجاز است. «قفلگشایی با چهره» غیرفعال است."</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"چهره تأیید نشد. دوباره امتحان کنید."</string>
- <string name="face_error_not_enrolled" msgid="7369928733504691611">"«بازگشایی با چهره» را راهاندازی نکردهاید."</string>
- <string name="face_error_hw_not_present" msgid="1070600921591729944">"«بازگشایی با چهره» در این دستگاه پشتیبانی نمیشود."</string>
+ <string name="face_error_not_enrolled" msgid="7369928733504691611">"«قفلگشایی با چهره» را راهاندازی نکردهاید."</string>
+ <string name="face_error_hw_not_present" msgid="1070600921591729944">"«قفلگشایی با چهره» در این دستگاه پشتیبانی نمیشود."</string>
<string name="face_error_security_update_required" msgid="5076017208528750161">"حسگر بهطور موقت غیرفعال است."</string>
<string name="face_name_template" msgid="3877037340223318119">"چهره <xliff:g id="FACEID">%d</xliff:g>"</string>
- <string name="face_app_setting_name" msgid="8130135875458467243">"استفاده از «بازگشایی با چهره»"</string>
+ <string name="face_app_setting_name" msgid="8130135875458467243">"استفاده از «قفلگشایی با چهره»"</string>
<string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"استفاده از قفل صفحه یا چهره"</string>
<string name="face_dialog_default_subtitle" msgid="6620492813371195429">"برای ادامه، از چهرهتان استفاده کنید"</string>
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"برای ادامه، از تشخیص چهره یا قفل صفحه استفاده کنید"</string>
@@ -887,7 +887,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"دوباره امتحان کنید"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"دوباره امتحان کنید"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"باز کردن قفل تمام قابلیتها و دادهها"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"دفعات تلاش برای «بازگشایی با چهره» از حداکثر مجاز بیشتر شد"</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"دفعات تلاش برای «قفلگشایی با چهره» از حداکثر مجاز بیشتر شد"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"سیم کارت موجود نیست"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"سیم کارت درون رایانهٔ لوحی نیست."</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"هیچ سیمکارتی در دستگاه Android TV شما قرار داده نشده است."</string>
@@ -957,7 +957,7 @@
<string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"گسترده کردن منطقه بازگشایی شده."</string>
<string name="keyguard_accessibility_slide_unlock" msgid="2968195219692413046">"باز کردن قفل با کشیدن انگشت روی صفحه."</string>
<string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"باز کردن قفل با الگو."</string>
- <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"بازگشایی با چهره."</string>
+ <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"قفلگشایی با چهره."</string>
<string name="keyguard_accessibility_pin_unlock" msgid="4020864007967340068">"باز کردن قفل با پین."</string>
<string name="keyguard_accessibility_sim_pin_unlock" msgid="4895939120871890557">"قفل پین سیمکارت باز شد."</string>
<string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"قفل Puk سیمکارت باز شد."</string>
@@ -1713,8 +1713,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"استفاده از میانبر"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"وارونگی رنگ"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"تصحیح رنگ"</string>
- <!-- no translation found for one_handed_mode_feature_name (2334330034828094891) -->
- <skip />
+ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"حالت تکحرکت"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"بسیار کمنور"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"کلیدهای میزان صدا پایین نگه داشته شد. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> روشن شد."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"کلیدهای میزان صدا پایین نگه داشته شد. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> خاموش شد."</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 270d594a..5655d10 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -609,14 +609,14 @@
<string-array name="fingerprint_error_vendor">
</string-array>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Sormenjälkikuvake"</string>
- <string name="permlab_manageFace" msgid="4569549381889283282">"hallinnoida Face Unlock ‑laitteistoa"</string>
+ <string name="permlab_manageFace" msgid="4569549381889283282">"hallinnoida kasvojentunnistusavauksen laitteistoa"</string>
<string name="permdesc_manageFace" msgid="6204569688492710471">"Sallii sovelluksen käyttää menetelmiä, joilla voidaan lisätä tai poistaa kasvomalleja."</string>
- <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"käyttää Face Unlock ‑laitteistoa"</string>
- <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Sallii sovelluksen käyttää Face Unlock ‑laitteistoa todennukseen"</string>
- <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Face Unlock"</string>
+ <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"käyttää kasvojentunnistusavauksen laitteistoa"</string>
+ <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Sallii sovelluksen käyttää kasvojentunnistusavauksen laitteistoa todennukseen"</string>
+ <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Kasvojentunnistusavaus"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Lisää kasvot uudelleen"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Lisää kasvosi uudelleen tunnistamisen parantamiseksi"</string>
- <string name="face_setup_notification_title" msgid="550617822603450009">"Ota Face Unlock käyttöön"</string>
+ <string name="face_setup_notification_title" msgid="550617822603450009">"Ota kasvojentunnistusavaus käyttöön"</string>
<string name="face_setup_notification_content" msgid="5463999831057751676">"Avaa puhelimesi lukitus katsomalla laitetta"</string>
<string name="fingerprint_setup_notification_title" msgid="2002630611398849495">"Ota käyttöön lisää tapoja avata lukitus"</string>
<string name="fingerprint_setup_notification_content" msgid="205578121848324852">"Napauta lisätäksesi sormenjälki"</string>
@@ -643,19 +643,19 @@
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="5085202213036026288">"Kasvoja ei voi vahvistaa. Laitteisto ei käytettäv."</string>
- <string name="face_error_timeout" msgid="522924647742024699">"Yritä käyttää Face Unlockia uudelleen."</string>
+ <string name="face_error_timeout" msgid="522924647742024699">"Yritä käyttää kasvojentunnistusavausta uudelleen."</string>
<string name="face_error_no_space" msgid="5649264057026021723">"Uutta kasvodataa ei voi tallentaa. Poista ensin vanhaa."</string>
<string name="face_error_canceled" msgid="2164434737103802131">"Kasvotoiminto peruutettu"</string>
- <string name="face_error_user_canceled" msgid="8553045452825849843">"Käyttäjä peruutti Face Unlockin."</string>
+ <string name="face_error_user_canceled" msgid="8553045452825849843">"Käyttäjä peruutti kasvojentunnistusavauksen."</string>
<string name="face_error_lockout" msgid="7864408714994529437">"Liian monta yritystä. Yritä myöhemmin uudelleen."</string>
- <string name="face_error_lockout_permanent" msgid="8277853602168960343">"Liian monta yritystä. Face Unlock poistettu käytöstä."</string>
+ <string name="face_error_lockout_permanent" msgid="8277853602168960343">"Liian monta yritystä. Kasvojentunnistusavaus poistettu käytöstä."</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"Kasvoja ei voi vahvistaa. Yritä uudelleen."</string>
- <string name="face_error_not_enrolled" msgid="7369928733504691611">"Et ole määrittänyt Face Unlockia."</string>
- <string name="face_error_hw_not_present" msgid="1070600921591729944">"Tämä laite ei tue Face Unlockia."</string>
+ <string name="face_error_not_enrolled" msgid="7369928733504691611">"Et ole määrittänyt kasvojentunnistusavausta."</string>
+ <string name="face_error_hw_not_present" msgid="1070600921591729944">"Tämä laite ei tue kasvojentunnistusavausta."</string>
<string name="face_error_security_update_required" msgid="5076017208528750161">"Tunnistin poistettu väliaikaisesti käytöstä."</string>
<string name="face_name_template" msgid="3877037340223318119">"Kasvot <xliff:g id="FACEID">%d</xliff:g>"</string>
- <string name="face_app_setting_name" msgid="8130135875458467243">"Käytä Face Unlockia"</string>
- <string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"Käytä Face Unlockia tai näytön lukitusta"</string>
+ <string name="face_app_setting_name" msgid="8130135875458467243">"Käytä kasvojentunnistusavausta"</string>
+ <string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"Käytä kasvojentunnistusavausta tai näytön lukitusta"</string>
<string name="face_dialog_default_subtitle" msgid="6620492813371195429">"Jatka kasvojesi avulla"</string>
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Jatka kasvojentunnistuksen tai näytön lukituksen avulla"</string>
<string-array name="face_error_vendor">
@@ -887,7 +887,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Yritä uudelleen"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"Yritä uudelleen"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"Käytä kaikkia ominaisuuksia avaamalla lukitus."</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Face Unlock -yrityksiä tehty suurin sallittu määrä."</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Kasvojentunnistusavauksen yrityksiä tehty suurin sallittu määrä."</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"Ei SIM-korttia"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"Tablet-laitteessa ei ole SIM-korttia."</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"Android TV ‑laitteessa ei ole SIM-korttia."</string>
@@ -957,7 +957,7 @@
<string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"Laajenna lukituksen poiston aluetta."</string>
<string name="keyguard_accessibility_slide_unlock" msgid="2968195219692413046">"Lukituksen poisto liu\'uttamalla."</string>
<string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"Lukituksen poisto salasanalla."</string>
- <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"Face Unlock"</string>
+ <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"Kasvojentunnistusavaus"</string>
<string name="keyguard_accessibility_pin_unlock" msgid="4020864007967340068">"Lukituksen poisto PIN-koodilla."</string>
<string name="keyguard_accessibility_sim_pin_unlock" msgid="4895939120871890557">"SIM-kortin PIN-koodin lukituksen avaus"</string>
<string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"SIM-kortin PUK-koodin lukituksen avaus"</string>
@@ -1022,8 +1022,7 @@
<string name="text_copied" msgid="2531420577879738860">"Teksti kopioitu leikepöydälle."</string>
<string name="copied" msgid="4675902854553014676">"Kopioitu"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> liitetty täältä: <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>"</string>
- <!-- no translation found for pasted_from_clipboard (7355790625710831847) -->
- <skip />
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> liitti leikepöydältäsi"</string>
<string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> on liittänyt kopioimasi tekstin"</string>
<string name="pasted_image" msgid="4729097394781491022">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> on liittänyt kopioimasi kuvan"</string>
<string name="pasted_content" msgid="646276353060777131">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> on liittänyt kopioimasi sisällön"</string>
@@ -1260,14 +1259,10 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Valmistellaan: <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Käynnistetään sovelluksia."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Viimeistellään päivitystä."</string>
- <!-- no translation found for fp_enrollment_powerbutton_intent_title (3385634173366119903) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_message (6582149052513682522) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_positive_button (5963520983910436791) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_negative_button (6465764183480190748) -->
- <skip />
+ <string name="fp_enrollment_powerbutton_intent_title" msgid="3385634173366119903">"Sammutetaanko näyttö?"</string>
+ <string name="fp_enrollment_powerbutton_intent_message" msgid="6582149052513682522">"Painoit virtapainiketta ottaessasi sormenjäljen käyttöön.\n\nTämä saa yleensä näytön sammumaan."</string>
+ <string name="fp_enrollment_powerbutton_intent_positive_button" msgid="5963520983910436791">"Laita pois päältä"</string>
+ <string name="fp_enrollment_powerbutton_intent_negative_button" msgid="6465764183480190748">"Peru"</string>
<string name="heavy_weight_notification" msgid="8382784283600329576">"<xliff:g id="APP">%1$s</xliff:g> käynnissä"</string>
<string name="heavy_weight_notification_detail" msgid="6802247239468404078">"Palaa peliin napauttamalla"</string>
<string name="heavy_weight_switcher_title" msgid="3861984210040100886">"Valitse peli"</string>
@@ -1718,8 +1713,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Käytä pikanäppäintä"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Käänteiset värit"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Värinkorjaus"</string>
- <!-- no translation found for one_handed_mode_feature_name (2334330034828094891) -->
- <skip />
+ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Yhden käden moodi"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Erittäin himmeä"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Äänenvoimakkuuspainikkeita painettiin pitkään. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> laitettiin päälle."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Äänenvoimakkuuspainikkeita painettiin pitkään. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> laitettiin pois päältä."</string>
@@ -1875,10 +1869,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Järjestelmänvalvoja päivitti tämän."</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Järjestelmänvalvoja poisti tämän."</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"Virransäästö laittaa tumman teeman päälle ja rajoittaa tai laittaa pois päältä taustatoimintoja, tiettyjä ominaisuuksia sekä joitakin visuaalisia tehosteita ja verkkoyhteyksiä.\n\n"<annotation id="url">"Lue lisää"</annotation></string>
+ <string name="battery_saver_description" msgid="8518809702138617167">"Virransäästö laittaa tumman teeman päälle ja rajoittaa tai laittaa pois päältä taustatoimintoja, tiettyjä ominaisuuksia sekä joitakin visuaalisia tehosteita ja verkkoyhteyksiä."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Data Saver estää joitakin sovelluksia lähettämästä tai vastaanottamasta tietoja taustalla, jotta datan käyttöä voidaan vähentää. Käytössäsi oleva sovellus voi yhä käyttää dataa, mutta se saattaa tehdä niin tavallista harvemmin. Tämä voi tarkoittaa esimerkiksi sitä, että kuva ladataan vasta, kun kosketat sitä."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Otetaanko Data Saver käyttöön?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"Ota käyttöön"</string>
@@ -1981,10 +1973,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ei ole juuri nyt saatavilla. Tästä vastaa <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"Lue lisää"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Peru keskeytys"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"Käytetäänkö työsovelluksia?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"Palauta työsovellukset ja ilmoitukset käyttöön"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Ota käyttöön"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"Sovellus ei ole käytettävissä"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ei ole nyt käytettävissä."</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index d717f5b..ec73dad 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -612,7 +612,7 @@
<string name="permlab_manageFace" msgid="4569549381889283282">"gérer le matériel de déverrouillage par reconnaissance faciale"</string>
<string name="permdesc_manageFace" msgid="6204569688492710471">"Permet à l\'appli d\'employer des méthodes d\'aj. et de suppr. de modèles de reconn. visage."</string>
<string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"utiliser le matériel de déverrouillage par reconnaissance faciale"</string>
- <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Permet à l\'appli d\'utiliser du matériel de déverr. par reconn faciale pour l\'authentific."</string>
+ <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Permet à l\'appli d\'utiliser du matériel de déverr. par reconn. faciale pour l\'authentific."</string>
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Déverrouillage par reconnaissance faciale"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Inscrivez votre visage à nouveau"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Pour améliorer la reconnaissance, veuillez enregistrer à nouveau votre visage"</string>
@@ -887,7 +887,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Réessayer"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"Réessayer"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"Déverr. pour acc. aux autres fonction. et données"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Nombre maximal autorisé de tentatives Face Unlock atteint."</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Nombre maximal atteint de tentatives de déverrouillage par reconnaissance faciale"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"Aucune carte SIM"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"Aucune carte SIM n\'est insérée dans la tablette."</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"Aucune carte SIM ne se trouve dans votre appareil Android TV."</string>
@@ -1022,8 +1022,7 @@
<string name="text_copied" msgid="2531420577879738860">"Le texte a été copié dans le presse-papiers."</string>
<string name="copied" msgid="4675902854553014676">"Copié"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> collé à partir de <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>"</string>
- <!-- no translation found for pasted_from_clipboard (7355790625710831847) -->
- <skip />
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> a collé du contenu de votre presse-papiers"</string>
<string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> a collé du texte que vous avez copié"</string>
<string name="pasted_image" msgid="4729097394781491022">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> a collé une image que vous avez copiée"</string>
<string name="pasted_content" msgid="646276353060777131">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> a collé le contenu que vous avez copié"</string>
@@ -1260,14 +1259,10 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Préparation de <xliff:g id="APPNAME">%1$s</xliff:g> en cours…"</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Lancement des applications…"</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Finalisation de la mise à jour."</string>
- <!-- no translation found for fp_enrollment_powerbutton_intent_title (3385634173366119903) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_message (6582149052513682522) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_positive_button (5963520983910436791) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_negative_button (6465764183480190748) -->
- <skip />
+ <string name="fp_enrollment_powerbutton_intent_title" msgid="3385634173366119903">"Éteindre l\'écran?"</string>
+ <string name="fp_enrollment_powerbutton_intent_message" msgid="6582149052513682522">"Pendant que vous configuriez votre empreinte digitale, vous avez appuyé sur l\'interrupteur.\n\nAppuyer sur ce bouton ferme habituellement l\'écran."</string>
+ <string name="fp_enrollment_powerbutton_intent_positive_button" msgid="5963520983910436791">"Éteindre"</string>
+ <string name="fp_enrollment_powerbutton_intent_negative_button" msgid="6465764183480190748">"Annuler"</string>
<string name="heavy_weight_notification" msgid="8382784283600329576">"<xliff:g id="APP">%1$s</xliff:g> en cours d\'exécution"</string>
<string name="heavy_weight_notification_detail" msgid="6802247239468404078">"Touchez pour revenir au jeu"</string>
<string name="heavy_weight_switcher_title" msgid="3861984210040100886">"Choisissez un jeu"</string>
@@ -1718,8 +1713,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Utiliser le raccourci"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Inversion des couleurs"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Correction des couleurs"</string>
- <!-- no translation found for one_handed_mode_feature_name (2334330034828094891) -->
- <skip />
+ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Mode Une main"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Réduction supplémentaire de la luminosité"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Touches de volume maintenues enfoncées. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> activé."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Touches de volume maintenues enfoncées. Service <xliff:g id="SERVICE_NAME">%1$s</xliff:g> désactivé."</string>
@@ -1875,10 +1869,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Mise à jour par votre administrateur"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Supprimé par votre administrateur"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"Le mode Économiseur de pile active le mode sombre et limite ou désactive l\'activité en arrière-plan, certains effets visuels, d\'autres fonctionnalités et certaines connexions réseau.\n\n"<annotation id="url">"En savoir plus"</annotation></string>
+ <string name="battery_saver_description" msgid="8518809702138617167">"Le mode Économiseur de pile active le thème sombre et limite ou désactive l\'activité en arrière-plan, certains effets visuels, certaines fonctionnalités et certaines connexions réseau."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Pour aider à diminuer l\'utilisation des données, la fonctionnalité Économiseur de données empêche certaines applications d\'envoyer ou de recevoir des données en arrière-plan. Une application que vous utilisez actuellement peut accéder à des données, mais peut le faire moins souvent. Cela peut signifier, par exemple, que les images ne s\'affichent pas jusqu\'à ce que vous les touchiez."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Activer l\'économiseur de données?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"Activer"</string>
@@ -1981,10 +1973,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"L\'application <xliff:g id="APP_NAME_0">%1$s</xliff:g> n\'est pas accessible pour le moment. Ceci est géré par <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"En savoir plus"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Réactiver l\'application"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"Activer applis professionnelles?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"Accédez à vos applications professionnelles et à vos notifications"</string>
<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>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 28990b4..22f699a 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -609,14 +609,14 @@
<string-array name="fingerprint_error_vendor">
</string-array>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Icône d\'empreinte digitale"</string>
- <string name="permlab_manageFace" msgid="4569549381889283282">"gérer les composants de Face Unlock"</string>
+ <string name="permlab_manageFace" msgid="4569549381889283282">"gérer le matériel de déverrouillage par authentification faciale"</string>
<string name="permdesc_manageFace" msgid="6204569688492710471">"Autorise l\'appli à invoquer des méthodes pour ajouter et supprimer des modèles de visages."</string>
- <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"utiliser les composants de Face Unlock"</string>
- <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Autorise l\'application à utiliser les composants de Face Unlock pour l\'authentification"</string>
- <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Face Unlock"</string>
+ <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"utiliser le matériel de déverrouillage par authentification faciale"</string>
+ <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Autorise l\'appli à utiliser le matériel de déverrouillage par authentification faciale"</string>
+ <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Déverrouillage par authentification faciale"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Enregistrer à nouveau votre visage"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Pour améliorer la reconnaissance, veuillez enregistrer à nouveau votre visage"</string>
- <string name="face_setup_notification_title" msgid="550617822603450009">"Configurer Face Unlock"</string>
+ <string name="face_setup_notification_title" msgid="550617822603450009">"Configurer le déverrouillage par authentification faciale"</string>
<string name="face_setup_notification_content" msgid="5463999831057751676">"Déverrouillez votre téléphone en le regardant"</string>
<string name="fingerprint_setup_notification_title" msgid="2002630611398849495">"Configurer d\'autres méthodes de déverrouillage"</string>
<string name="fingerprint_setup_notification_content" msgid="205578121848324852">"Appuyez pour ajouter une empreinte digitale"</string>
@@ -643,19 +643,19 @@
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="5085202213036026288">"Imposs. valider visage. Matériel non disponible."</string>
- <string name="face_error_timeout" msgid="522924647742024699">"Réessayez d\'activer Face Unlock."</string>
+ <string name="face_error_timeout" msgid="522924647742024699">"Réessayez d\'activer le déverrouillage."</string>
<string name="face_error_no_space" msgid="5649264057026021723">"Impossible stocker nouv. visages. Veuillez en supprimer un."</string>
<string name="face_error_canceled" msgid="2164434737103802131">"Opération de reconnaissance faciale annulée."</string>
- <string name="face_error_user_canceled" msgid="8553045452825849843">"Face Unlock annulé par l\'utilisateur."</string>
+ <string name="face_error_user_canceled" msgid="8553045452825849843">"Déverrouillage par authentification faciale annulé par l\'utilisateur"</string>
<string name="face_error_lockout" msgid="7864408714994529437">"Trop de tentatives. Réessayez plus tard."</string>
- <string name="face_error_lockout_permanent" msgid="8277853602168960343">"Tentatives trop nombreuses. Désactivation de Face Unlock."</string>
+ <string name="face_error_lockout_permanent" msgid="8277853602168960343">"Trop de tentatives. Déverrouillage par authentification faciale désactivé."</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"Impossible de valider votre visage. Réessayez."</string>
- <string name="face_error_not_enrolled" msgid="7369928733504691611">"Face Unlock n\'est pas configuré."</string>
- <string name="face_error_hw_not_present" msgid="1070600921591729944">"Face Unlock n\'est pas compatible avec cet appareil."</string>
+ <string name="face_error_not_enrolled" msgid="7369928733504691611">"Déverrouillage par authentification faciale non configuré"</string>
+ <string name="face_error_hw_not_present" msgid="1070600921591729944">"Déverrouillage par authentification faciale non compatible"</string>
<string name="face_error_security_update_required" msgid="5076017208528750161">"Capteur temporairement désactivé."</string>
<string name="face_name_template" msgid="3877037340223318119">"Visage <xliff:g id="FACEID">%d</xliff:g>"</string>
- <string name="face_app_setting_name" msgid="8130135875458467243">"Utiliser Face Unlock"</string>
- <string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"Utiliser Face Lock ou le verrouillage de l\'écran"</string>
+ <string name="face_app_setting_name" msgid="8130135875458467243">"Utiliser déverrouillage facial"</string>
+ <string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"Utiliser déverrouillage par authent. faciale ou verrouillage écran"</string>
<string name="face_dialog_default_subtitle" msgid="6620492813371195429">"Utilisez la reconnaissance faciale pour continuer"</string>
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Utilisez la reconnaissance faciale ou le verrouillage de l\'écran pour continuer"</string>
<string-array name="face_error_vendor">
@@ -887,7 +887,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Veuillez réessayer."</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"Veuillez réessayer."</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"Déverr. pour autres fonctionnalités et données"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Nombre maximal autorisé de tentatives Face Unlock atteint."</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Nombre maximal de tentatives de déverrouillage par authentification faciale atteint"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"Pas de carte SIM"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"Aucune carte SIM n\'est insérée dans la tablette."</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"Aucune carte SIM n\'est installée dans votre appareil Android TV."</string>
@@ -957,7 +957,7 @@
<string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"Développer la zone de déverrouillage"</string>
<string name="keyguard_accessibility_slide_unlock" msgid="2968195219692413046">"Déverrouillage en faisant glisser votre doigt sur l\'écran"</string>
<string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"Déverrouillage par schéma"</string>
- <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"Déverrouillage par reconnaissance faciale"</string>
+ <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"Déverrouillage par authentification faciale"</string>
<string name="keyguard_accessibility_pin_unlock" msgid="4020864007967340068">"Déverrouillage par code PIN"</string>
<string name="keyguard_accessibility_sim_pin_unlock" msgid="4895939120871890557">"Déverrouillage de la carte SIM à l\'aide d\'un code."</string>
<string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"Déverrouillage de la carte SIM à l\'aide d\'une clé PUK."</string>
@@ -1869,10 +1869,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Mis à jour par votre administrateur"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Supprimé par votre administrateur"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"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.\n\n"<annotation id="url">"En savoir plus"</annotation></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_button" msgid="4399405762586419726">"Activer"</string>
@@ -1975,10 +1973,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"L\'application <xliff:g id="APP_NAME_0">%1$s</xliff:g> n\'est pas disponible pour le moment. Cette suspension est gérée par l\'application <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"En savoir plus"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Débloquer l\'application"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"Activer les applis pros ?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"Accéder à vos applis et notifications professionnelles"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Activer"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"Application non disponible"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> n\'est pas disponible pour le moment."</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index e2bd3cb..bbc868f 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -1869,10 +1869,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Actualizado polo teu administrador"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Eliminado polo teu administrador"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"Aceptar"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"Coa función Aforro de batería, actívase o tema escuro e restrínxense ou desactívanse a actividade en segundo plano, algúns efectos visuais e determinadas funcións e conexións de rede.\n\n"<annotation id="url">"Máis información"</annotation></string>
+ <string name="battery_saver_description" msgid="8518809702138617167">"Coa función Aforro de batería, actívase o tema escuro e restrínxense ou desactívanse a actividade en segundo plano, algúns efectos visuais e determinadas funcións e conexións de rede."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Para contribuír a reducir o uso de datos, o aforro de datos impide que algunhas aplicacións envíen ou reciban datos en segundo plano. Cando esteas utilizando unha aplicación, esta poderá acceder aos datos, pero é posible que o faga con menos frecuencia. Por exemplo, poida que as imaxes non se mostren ata que as toques."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Queres activar o aforro de datos?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"Activar"</string>
@@ -1975,10 +1973,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"A aplicación <xliff:g id="APP_NAME_0">%1$s</xliff:g> non está dispoñible neste momento. A dispoñibilidade está xestionada por <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"Máis información"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Volver activar aplicación"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"Activar as apps do traballo?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"Obtén acceso ás túas aplicacións e notificacións do traballo"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Activar"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"A aplicación non está dispoñible"</string>
<string name="app_blocked_message" msgid="542972921087873023">"A aplicación <xliff:g id="APP_NAME">%1$s</xliff:g> non está dispoñible neste momento."</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index 4f32f29..6bf1ff8 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -1022,8 +1022,7 @@
<string name="text_copied" msgid="2531420577879738860">"ક્લિપબોર્ડ પર ટેક્સ્ટ કૉપિ કરી."</string>
<string name="copied" msgid="4675902854553014676">"કૉપિ કરેલ"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>માંથી કૉપિ કરાયેલો ડેટા <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>માં પેસ્ટ કરવામાં આવ્યો"</string>
- <!-- no translation found for pasted_from_clipboard (7355790625710831847) -->
- <skip />
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> દ્વારા તમારા ક્લિપબોર્ડ પરથી પેસ્ટ કરવામાં આવ્યું"</string>
<string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> દ્વારા તમે કૉપિ કરેલી ટેક્સ્ટ પેસ્ટ કરાઈ"</string>
<string name="pasted_image" msgid="4729097394781491022">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> દ્વારા તમે કૉપિ કરેલી છબી પેસ્ટ કરાઈ"</string>
<string name="pasted_content" msgid="646276353060777131">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> દ્વારા તમે કૉપિ કરેલું કન્ટેન્ટ પેસ્ટ કરાયું"</string>
@@ -1260,14 +1259,10 @@
<string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> તૈયાર કરી રહ્યું છે."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"ઍપ્લિકેશનો શરૂ કરી રહ્યાં છે."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"બૂટ સમાપ્ત કરી રહ્યાં છે."</string>
- <!-- no translation found for fp_enrollment_powerbutton_intent_title (3385634173366119903) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_message (6582149052513682522) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_positive_button (5963520983910436791) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_negative_button (6465764183480190748) -->
- <skip />
+ <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="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>
@@ -1718,8 +1713,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"શૉર્ટકટનો ઉપયોગ કરો"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"વિપરીત રંગમાં બદલવું"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"રંગ સુધારણા"</string>
- <!-- no translation found for one_handed_mode_feature_name (2334330034828094891) -->
- <skip />
+ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"એક-હાથે વાપરો મોડ"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"એક્સ્ટ્રા ડિમ"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"વૉલ્યૂમ કી દબાવી રાખો. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ચાલુ કરી."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"વૉલ્યૂમ કી દબાવી રાખો. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> બંધ કરી."</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index b4594e1..422b4fa 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -611,9 +611,9 @@
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"फ़िंगरप्रिंट आइकॉन"</string>
<string name="permlab_manageFace" msgid="4569549381889283282">"\'मालिक का चेहरा पहचानकर अनलॉक\' वाला हार्डवेयर प्रबंधित करें"</string>
<string name="permdesc_manageFace" msgid="6204569688492710471">"ऐप्लिकेशन को चेहरे के टेम्पलेट इस्तेमाल के तरीके जोड़ने और मिटाने की मंज़ूरी मिलती है."</string>
- <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"\'मालिक का चेहरा पहचानकर अनलॉक\' वाला हार्डवेयर इस्तेमाल करें"</string>
- <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"ऐप्लिकेशन को \'मालिक का चेहरा पहचानकर अनलॉक\' वाले हार्डवेयर के इस्तेमाल की मंज़ूरी देता है"</string>
- <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"मालिक का चेहरा पहचानकर अनलॉक"</string>
+ <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"फ़ेस अनलॉक हार्डवेयर इस्तेमाल करें"</string>
+ <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"फ़ेस अनलॉक हार्डवेयर के इस्तेमाल की मंज़ूरी देता है"</string>
+ <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"फ़ेस अनलॉक"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"अपना चेहरा फिर से दर्ज करें"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"कृपया अपना चेहरा फिर से दर्ज करें ताकि आपको बेहतर तरीके से पहचाना जा सके"</string>
<string name="face_setup_notification_title" msgid="550617822603450009">"फ़ेस अनलॉक की सुविधा सेट अप करें"</string>
@@ -643,7 +643,7 @@
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="5085202213036026288">"चेहरा नहीं पहचान पा रहे. हार्डवेयर उपलब्ध नहीं है."</string>
- <string name="face_error_timeout" msgid="522924647742024699">"\'मालिक का चेहरा पहचानकर अनलॉक\' फिर से आज़माएं."</string>
+ <string name="face_error_timeout" msgid="522924647742024699">"फ़ेस अनलॉक की सुविधा फिर से आज़माएं."</string>
<string name="face_error_no_space" msgid="5649264057026021723">"चेहरे का नया डेटा सेव नहीं हो सकता. कोई पुराना डेटा मिटाएं."</string>
<string name="face_error_canceled" msgid="2164434737103802131">"चेहरा पहचानने की कार्रवाई रद्द की गई."</string>
<string name="face_error_user_canceled" msgid="8553045452825849843">"उपयोगकर्ता ने \'मालिक का चेहरा पहचानकर अनलॉक\' रद्द की."</string>
@@ -651,7 +651,7 @@
<string name="face_error_lockout_permanent" msgid="8277853602168960343">"कई बार कोशिश की जा चुकी है. \'मालिक का चेहरा पहचानकर अनलॉक\' बंद है."</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"चेहरा नहीं पहचान पा रहे. फिर से कोशिश करें."</string>
<string name="face_error_not_enrolled" msgid="7369928733504691611">"आपने \'मालिक का चेहरा पहचानकर अनलॉक\' सेट नहीं की है."</string>
- <string name="face_error_hw_not_present" msgid="1070600921591729944">"इस डिवाइस पर \'मालिक का चेहरा पहचानकर अनलॉक\' काम नहीं करती है."</string>
+ <string name="face_error_hw_not_present" msgid="1070600921591729944">"इस डिवाइस पर फ़ेस अनलॉक की सुविधा काम नहीं करती है."</string>
<string name="face_error_security_update_required" msgid="5076017208528750161">"सेंसर कुछ समय के लिए बंद कर दिया गया है."</string>
<string name="face_name_template" msgid="3877037340223318119">"चेहरा <xliff:g id="FACEID">%d</xliff:g>"</string>
<string name="face_app_setting_name" msgid="8130135875458467243">"\'फ़ेस अनलॉक\' इस्तेमाल करें"</string>
@@ -1869,10 +1869,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"आपके व्यवस्थापक ने अपडेट किया है"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"आपके व्यवस्थापक ने हटा दिया है"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ठीक है"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"बैटरी सेवर, गहरे रंग वाली थीम को चालू करता है. साथ ही, यह बैकग्राउंड की गतिविधि, कुछ विज़ुअल इफ़ेक्ट, कुछ खास सुविधाओं, और कुछ खास तरह के इंटरनेट कनेक्शन इस्तेमाल करने से डिवाइस को रोकता है या इन्हें बंद कर देता है.\n\n"<annotation id="url">"ज़्यादा जानें"</annotation></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>
@@ -1975,10 +1973,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"फ़िलहाल <xliff:g id="APP_NAME_0">%1$s</xliff:g> उपलब्ध नहीं है. इसे <xliff:g id="APP_NAME_1">%2$s</xliff:g> के ज़रिए प्रबंधित किया जाता है."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"ज़्यादा जानें"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"ऐप्लिकेशन पर लगी रोक हटाएं"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"ऑफ़िस के काम से जुड़े ऐप्लिकेशन चालू करना चाहते हैं?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"अपने ऑफ़िस के काम से जुड़े ऐप्लिकेशन और सूचनाओं का ऐक्सेस पाएं"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"चालू करें"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"ऐप्लिकेशन उपलब्ध नहीं है"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> इस समय उपलब्ध नहीं है."</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 8759f7a..acccfa9 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -658,7 +658,7 @@
<string name="face_error_security_update_required" msgid="5076017208528750161">"Senzor je privremeno onemogućen."</string>
<string name="face_name_template" msgid="3877037340223318119">"Lice <xliff:g id="FACEID">%d</xliff:g>"</string>
<string name="face_app_setting_name" msgid="8130135875458467243">"Upotreba otključavanja licem"</string>
- <string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"Upotreba lica ili zaključavanja zaslona"</string>
+ <string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"Upotreba otključavanja licem ili zaključavanja zaslona"</string>
<string name="face_dialog_default_subtitle" msgid="6620492813371195429">"Autentificirajte se licem da biste nastavili"</string>
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Za nastavak se identificirajte licem ili vjerodajnicom zaključavanja zaslona"</string>
<string-array name="face_error_vendor">
@@ -890,7 +890,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Pokušajte ponovo"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"Pokušajte ponovo"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"Otključajte za sve značajke i podatke"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Premašen je maksimalni broj Otključavanja licem"</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Premašen je maksimalni broj pokušaja otključavanja licem"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"Nema SIM kartice"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"U tabletnom uređaju nema SIM kartice."</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"Na Android TV uređaju nema SIM kartice."</string>
@@ -1892,10 +1892,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Ažurirao administrator"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Izbrisao administrator"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"U redu"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"Štednja baterije uključuje tamnu temu i ograničava ili isključuje aktivnosti u pozadini, neke vizualne efekte, određene značajke i neke mrežne veze.\n\n"<annotation id="url">"Saznajte više"</annotation></string>
+ <string name="battery_saver_description" msgid="8518809702138617167">"Štednja baterije uključuje tamnu temu i ograničava ili isključuje aktivnosti u pozadini, neke vizualne efekte, određene značajke i neke mrežne veze."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Da bi se smanjio podatkovni promet, značajka Štednja podatkovnog prometa onemogućuje nekim aplikacijama slanje ili primanje podataka u pozadini. Aplikacija koju trenutačno upotrebljavate može pristupiti podacima, no možda će to činiti rjeđe. To može značiti da se, na primjer, slike neće prikazivati dok ih ne dodirnete."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Uključiti Štednju podatkovnog prometa?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"Uključi"</string>
@@ -2007,10 +2005,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"Aplikacija <xliff:g id="APP_NAME_0">%1$s</xliff:g> trenutačno nije dostupna. Ovime upravlja aplikacija <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"Saznajte više"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Prekini pauzu aplikacije"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"Uključiti poslovne aplikacije?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"Pristupite svojim poslovnim aplikacijama i obavijestima"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Uključi"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"Aplikacija nije dostupna"</string>
<string name="app_blocked_message" msgid="542972921087873023">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> trenutačno nije dostupna."</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index dd4afa53..4671f4a 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1713,8 +1713,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Billentyűparancs használata"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Színek invertálása"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Színkorrekció"</string>
- <!-- no translation found for one_handed_mode_feature_name (2334330034828094891) -->
- <skip />
+ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Egykezes mód"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Extrasötét"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Nyomva tartotta a hangerőgombokat. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> bekapcsolva."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Nyomva tartotta a hangerőgombokat. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> kikapcsolva."</string>
@@ -1870,10 +1869,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"A rendszergazda által frissítve"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"A rendszergazda által törölve"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"Az Akkumulátorkímélő mód bekapcsolja a Sötét témát, és korlátozza vagy kikapcsolja a háttérbeli tevékenységeket, valamint bizonyos vizuális effekteket, funkciókat és hálózati kapcsolatokat.\n\n"<annotation id="url">"További információ"</annotation></string>
+ <string name="battery_saver_description" msgid="8518809702138617167">"Az Akkumulátorkímélő mód bekapcsolja a Sötét témát, és korlátozza vagy kikapcsolja a háttérbeli tevékenységeket, valamint bizonyos vizuális effekteket, funkciókat és hálózati kapcsolatokat."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Az adatforgalom csökkentése érdekében az Adatforgalom-csökkentő megakadályozza, hogy egyes alkalmazások adatokat küldjenek vagy fogadjanak a háttérben. Az Ön által jelenleg használt alkalmazások hozzáférhetnek az adatokhoz, de csak ritkábban. Ez például azt jelentheti, hogy a képek csak rákoppintás után jelennek meg."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Bekapcsolja az Adatforgalom-csökkentőt?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"Bekapcsolás"</string>
@@ -1976,10 +1973,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"A(z) <xliff:g id="APP_NAME_0">%1$s</xliff:g> alkalmazás jelenleg nem áll rendelkezésre. Ezt a(z) <xliff:g id="APP_NAME_1">%2$s</xliff:g> kezeli."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"További információ"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Alkalmazás szüneteltetésének feloldása"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"Bekapcsolja a munkaappokat?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"Hozzáférést kaphat munkahelyi alkalmazásaihoz és értesítéseihez"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Bekapcsolás"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"Az alkalmazás nem hozzáférhető"</string>
<string name="app_blocked_message" msgid="542972921087873023">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> jelenleg nem hozzáférhető."</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 988010b..fe6be14 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -887,7 +887,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Կրկին փորձեք"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"Կրկին փորձեք"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"Ապակողպեք՝ բոլոր գործառույթներն ու տվյալներն օգտագործելու համար"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Առավելագույն Դեմքով ապակողպման փորձերը գերազանցված են"</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Դեմքով ապակողպման փորձերի առավելագույն քանակը գերազանցված են"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"SIM քարտ չկա"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"Գրասալիկում SIM քարտ չկա:"</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"Ձեր Android սարքում SIM քարտ չկա։"</string>
@@ -1022,8 +1022,7 @@
<string name="text_copied" msgid="2531420577879738860">"Տեքստը պատճենված է սեղմատախտակին:"</string>
<string name="copied" msgid="4675902854553014676">"Պատճենվեց"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> հավելվածը տվյալներ տեղադրեց <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> հավելվածից"</string>
- <!-- no translation found for pasted_from_clipboard (7355790625710831847) -->
- <skip />
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> հավելվածը տվյալներ է տեղադրել ձեր սեղմատախտակից"</string>
<string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> հավելվածը տեղադրեց ձեր պատճենած տեքստը"</string>
<string name="pasted_image" msgid="4729097394781491022">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> հավելվածը տեղադրեց ձեր պատճենած պատկերը"</string>
<string name="pasted_content" msgid="646276353060777131">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> հավելվածը տեղադրեց ձեր պատճենած բովանդակությունը"</string>
@@ -1260,14 +1259,10 @@
<string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> հավելվածը պատրաստվում է:"</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Հավելվածները մեկնարկում են:"</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Բեռնումն ավարտվում է:"</string>
- <!-- no translation found for fp_enrollment_powerbutton_intent_title (3385634173366119903) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_message (6582149052513682522) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_positive_button (5963520983910436791) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_negative_button (6465764183480190748) -->
- <skip />
+ <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="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>
@@ -1718,8 +1713,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Օգտագործել դյուրանցումը"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Գունաշրջում"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Գունաշտկում"</string>
- <!-- no translation found for one_handed_mode_feature_name (2334330034828094891) -->
- <skip />
+ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Մեկ ձեռքի ռեժիմ"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Հավելյալ խամրեցում"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Ձայնի կարգավորման կոճակները սեղմվեցին։ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ծառայությունը միացավ։"</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Ձայնի կարգավորման կոճակները սեղմվեցին։ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ծառայությունն անջատվեց։"</string>
@@ -1875,10 +1869,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Թարմացվել է ձեր ադմինիստրատորի կողմից"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Ջնջվել է ձեր ադմինիստրատորի կողմից"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"Եղավ"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"«Մարտկոցի տնտեսում» գործառույթը միացնում է մուգ թեման և անջատում կամ սահմանափակում է աշխատանքը ֆոնային ռեժիմում, որոշ վիզուալ էֆեկտներ, ցանցային միացումներ և այլ գործառույթներ։\n\n"<annotation id="url">"Իմանալ ավելին"</annotation></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>
@@ -1981,10 +1973,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> հավելվածը հասանելի չէ։ Դրա աշխատանքը սահմանափակում է <xliff:g id="APP_NAME_1">%2$s</xliff:g> հավելվածը։"</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"Մանրամասն"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Չեղարկել դադարեցումը"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"Միացնե՞լ հավելվածները"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"Միացրեք աշխատանքային հավելվածներն ու ծանուցումները"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Միացնել"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"Հավելվածը հասանելի չէ"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածն այս պահին հասանելի չէ։"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 990f94d..b4c9aa1 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1022,8 +1022,7 @@
<string name="text_copied" msgid="2531420577879738860">"Teks disalin ke papan klip."</string>
<string name="copied" msgid="4675902854553014676">"Disalin"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ditempelkan dari <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>"</string>
- <!-- no translation found for pasted_from_clipboard (7355790625710831847) -->
- <skip />
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> menempel dari papan klip"</string>
<string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> menempelkan teks yang Anda salin"</string>
<string name="pasted_image" msgid="4729097394781491022">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> menempelkan gambar yang Anda salin"</string>
<string name="pasted_content" msgid="646276353060777131">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> menempelkan konten yang Anda salin"</string>
@@ -1260,14 +1259,10 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Menyiapkan <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Memulai aplikasi."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Menyelesaikan boot."</string>
- <!-- no translation found for fp_enrollment_powerbutton_intent_title (3385634173366119903) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_message (6582149052513682522) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_positive_button (5963520983910436791) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_negative_button (6465764183480190748) -->
- <skip />
+ <string name="fp_enrollment_powerbutton_intent_title" msgid="3385634173366119903">"Nonaktifkan layar?"</string>
+ <string name="fp_enrollment_powerbutton_intent_message" msgid="6582149052513682522">"Saat menyiapkan sidik jari, Anda menekan Tombol daya.\n\nTindakan ini biasanya akan menonaktifkan layar."</string>
+ <string name="fp_enrollment_powerbutton_intent_positive_button" msgid="5963520983910436791">"Nonaktifkan"</string>
+ <string name="fp_enrollment_powerbutton_intent_negative_button" msgid="6465764183480190748">"Batal"</string>
<string name="heavy_weight_notification" msgid="8382784283600329576">"<xliff:g id="APP">%1$s</xliff:g> sedang berjalan"</string>
<string name="heavy_weight_notification_detail" msgid="6802247239468404078">"Ketuk untuk kembali ke game"</string>
<string name="heavy_weight_switcher_title" msgid="3861984210040100886">"Pilih game"</string>
@@ -1874,10 +1869,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Diupdate oleh admin Anda"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Dihapus oleh admin Anda"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"Oke"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"Penghemat Baterai akan mengaktifkan Tema gelap dan membatasi atau menonaktifkan aktivitas latar belakang, beberapa efek visual, fitur tertentu, dan beberapa koneksi jaringan.\n\n"<annotation id="url">"Pelajari lebih lanjut"</annotation></string>
+ <string name="battery_saver_description" msgid="8518809702138617167">"Penghemat Baterai akan mengaktifkan Tema gelap dan membatasi atau menonaktifkan aktivitas latar belakang, beberapa efek visual, fitur tertentu, dan beberapa koneksi jaringan."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Untuk membantu mengurangi penggunaan data, Penghemat Data mencegah beberapa aplikasi mengirim atau menerima data di latar belakang. Aplikasi yang sedang digunakan dapat mengakses data, tetapi frekuensinya agak lebih jarang. Misalnya saja, gambar hanya akan ditampilkan setelah diketuk."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Aktifkan Penghemat Data?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"Aktifkan"</string>
@@ -1980,10 +1973,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> saat ini tidak tersedia. Aplikasi ini dikelola oleh <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"Pelajari lebih lanjut"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Batalkan jeda aplikasi"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"Aktifkan aplikasi kerja?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"Dapatkan akses ke aplikasi kerja dan notifikasi"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Aktifkan"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"Aplikasi tidak tersedia"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> tidak tersedia saat ini."</string>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index ba889b6..2d28175 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -612,7 +612,7 @@
<string name="permlab_manageFace" msgid="4569549381889283282">"stjórna vélbúnaði andlitsopnunar"</string>
<string name="permdesc_manageFace" msgid="6204569688492710471">"Leyfir forritinu að beita aðferðum til að bæta við og eyða andlitssniðmátum til notkunar."</string>
<string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"nota vélbúnað andlitsopnunar"</string>
- <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Leyfir forritinu að nota andlitsopnunarvélbúnað til auðkenningar"</string>
+ <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Leyfir forritinu að nota vélbúnað andlitsopnunar til auðkenningar"</string>
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Andlitsopnun"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Skráðu andlitið þitt aftur"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Skráðu andlitið þitt til að bæta kennsl"</string>
@@ -887,7 +887,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Reyndu aftur"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"Reyndu aftur"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"Taktu úr lás til að sjá alla eiginleika og gögn"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Hámarksfjölda tilrauna til að opna með andliti náð"</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Hámarksfjölda tilrauna til andlitsopnunar náð"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"Ekkert SIM-kort"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"Ekkert SIM-kort í spjaldtölvunni."</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"Ekkert SIM-kort er í Android TV tækinu."</string>
@@ -957,7 +957,7 @@
<string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"Stækka opnunarsvæði."</string>
<string name="keyguard_accessibility_slide_unlock" msgid="2968195219692413046">"Opnun með stroku."</string>
<string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"Opnun með mynstri."</string>
- <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"Opnun með andliti."</string>
+ <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"Andlitsopnun."</string>
<string name="keyguard_accessibility_pin_unlock" msgid="4020864007967340068">"Opnun með PIN-númeri."</string>
<string name="keyguard_accessibility_sim_pin_unlock" msgid="4895939120871890557">"Taka PIN-númer SIM-korts úr lás."</string>
<string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"Taka PUK-númer SIM-korts úr lás."</string>
@@ -1713,8 +1713,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Nota flýtileið"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Umsnúningur lita"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Litaleiðrétting"</string>
- <!-- no translation found for one_handed_mode_feature_name (2334330034828094891) -->
- <skip />
+ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Einhent stilling"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Mjög dökkt"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Hljóðstyrkstökkum haldið inni. Kveikt á <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Hljóðstyrkstökkum haldið inni. Slökkt á <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
@@ -1870,10 +1869,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Kerfisstjóri uppfærði"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Kerfisstjóri eyddi"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"Í lagi"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"Rafhlöðusparnaður kveikir á dökku þema og takmarkar eða slekkur á bakgrunnsvirkni, sumum áhrifum, tilteknum eiginleikum og sumum nettengingum.\n\n"<annotation id="url">"Nánar"</annotation></string>
+ <string name="battery_saver_description" msgid="8518809702138617167">"Rafhlöðusparnaður kveikir á dökku þema og takmarkar eða slekkur á bakgrunnsvirkni, sumum áhrifum, tilteknum eiginleikum og sumum nettengingum."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Gagnasparnaður getur hjálpað til við að draga úr gagnanotkun með því að hindra forrit í að senda eða sækja gögn í bakgrunni. Forrit sem er í notkun getur náð í gögn, en gerir það kannski sjaldnar. Niðurstaðan getur verið að myndir eru ekki birtar fyrr en þú ýtir á þær, svo dæmi sé tekið."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Kveikja á gagnasparnaði?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"Kveikja"</string>
@@ -1976,10 +1973,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> er ekki í boði eins og er. Þessu er stjórnað með <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"Nánari upplýsingar"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Halda áfram að nota"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"Kveikja á vinnuforritum?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"Fá aðgang að vinnuforritum og tilkynningum"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Kveikja"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"Forrit er ekki tiltækt"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> er ekki tiltækt núna."</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 411c4e1..116b2082 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -609,14 +609,14 @@
<string-array name="fingerprint_error_vendor">
</string-array>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Icona dell\'impronta"</string>
- <string name="permlab_manageFace" msgid="4569549381889283282">"gestione dell\'hardware per Sblocco con il volto"</string>
+ <string name="permlab_manageFace" msgid="4569549381889283282">"gestione dell\'hardware per lo sblocco con il volto"</string>
<string name="permdesc_manageFace" msgid="6204569688492710471">"Consente all\'app di richiamare i metodi per aggiungere e rimuovere i modelli di volti."</string>
- <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"utilizzo dell\'hardware per Sblocco con il volto"</string>
- <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Consente all\'app di utilizzare hardware per l\'autenticazione con Sblocco con il volto"</string>
+ <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"utilizzo dell\'hardware per lo sblocco con il volto"</string>
+ <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Consente all\'app di usare hardware per l\'autenticazione mediante lo sblocco con il volto"</string>
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Sblocco con il volto"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Registra di nuovo il volto"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Per migliorare il riconoscimento, registra di nuovo il tuo volto"</string>
- <string name="face_setup_notification_title" msgid="550617822603450009">"Configura Sblocco con il volto"</string>
+ <string name="face_setup_notification_title" msgid="550617822603450009">"Configura lo sblocco con il volto"</string>
<string name="face_setup_notification_content" msgid="5463999831057751676">"Sblocca il telefono guardandolo"</string>
<string name="fingerprint_setup_notification_title" msgid="2002630611398849495">"Configura altri modi per sbloccare"</string>
<string name="fingerprint_setup_notification_content" msgid="205578121848324852">"Tocca per aggiungere un\'impronta"</string>
@@ -643,19 +643,19 @@
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="5085202213036026288">"Imposs. verificare volto. Hardware non disponibile."</string>
- <string name="face_error_timeout" msgid="522924647742024699">"Riprova Sblocco con il volto."</string>
+ <string name="face_error_timeout" msgid="522924647742024699">"Riprova lo sblocco con il volto."</string>
<string name="face_error_no_space" msgid="5649264057026021723">"Imposs. salvare dati nuovi volti. Elimina un volto vecchio."</string>
<string name="face_error_canceled" msgid="2164434737103802131">"Operazione associata al volto annullata."</string>
<string name="face_error_user_canceled" msgid="8553045452825849843">"Sblocco con il volto annullato dall\'utente."</string>
<string name="face_error_lockout" msgid="7864408714994529437">"Troppi tentativi. Riprova più tardi."</string>
- <string name="face_error_lockout_permanent" msgid="8277853602168960343">"Troppi tentativi. Sblocco con il volto disattivato"</string>
+ <string name="face_error_lockout_permanent" msgid="8277853602168960343">"Troppi tentativi. Lo sblocco con il volto è disattivato."</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"Impossibile verificare il volto. Riprova."</string>
- <string name="face_error_not_enrolled" msgid="7369928733504691611">"Non hai configurato Sblocco con il volto."</string>
+ <string name="face_error_not_enrolled" msgid="7369928733504691611">"Non hai configurato lo sblocco con il volto."</string>
<string name="face_error_hw_not_present" msgid="1070600921591729944">"Sblocco con il volto non supportato su questo dispositivo."</string>
<string name="face_error_security_update_required" msgid="5076017208528750161">"Sensore temporaneamente disattivato."</string>
<string name="face_name_template" msgid="3877037340223318119">"Volto <xliff:g id="FACEID">%d</xliff:g>"</string>
- <string name="face_app_setting_name" msgid="8130135875458467243">"Usa Sblocco con il volto"</string>
- <string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"Usa Sblocco con il volto o il blocco schermo"</string>
+ <string name="face_app_setting_name" msgid="8130135875458467243">"Usa lo sblocco con il volto"</string>
+ <string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"Usa lo sblocco con il volto o il blocco schermo"</string>
<string name="face_dialog_default_subtitle" msgid="6620492813371195429">"Usa il tuo volto per continuare"</string>
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Per continuare devi usare il tuo volto o il tuo blocco schermo"</string>
<string-array name="face_error_vendor">
@@ -887,7 +887,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Riprova"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"Riprova"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"Sblocca per accedere a funzioni e dati"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Numero massimo di tentativi di Sblocco con il volto superato"</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Numero massimo di tentativi di sblocco con il volto superato"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"Nessuna SIM"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"Nessuna scheda SIM presente nel tablet."</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"Nessuna scheda SIM nel dispositivo Android TV."</string>
@@ -1713,8 +1713,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Usa scorciatoia"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Inversione dei colori"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Correzione del colore"</string>
- <!-- no translation found for one_handed_mode_feature_name (2334330034828094891) -->
- <skip />
+ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Modalità one-hand"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Attenuazione extra"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Tieni premuti i tasti del volume. Servizio <xliff:g id="SERVICE_NAME">%1$s</xliff:g> attivato."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Tieni premuti i tasti del volume. Servizio <xliff:g id="SERVICE_NAME">%1$s</xliff:g> disattivato."</string>
@@ -1870,10 +1869,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Aggiornato dall\'amministratore"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Eliminato dall\'amministratore"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"L\'opzione Risparmio energetico attiva il tema scuro e limita o disattiva l\'attività in background, nonché alcuni effetti visivi, funzionalità e connessioni di rete.\n\n"<annotation id="url">"Scopri di più"</annotation></string>
+ <string name="battery_saver_description" msgid="8518809702138617167">"L\'opzione Risparmio energetico attiva il tema scuro e limita o disattiva l\'attività in background, nonché alcuni effetti visivi, funzionalità e connessioni di rete."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Per contribuire a ridurre l\'utilizzo dei dati, la funzione Risparmio dati impedisce ad alcune app di inviare o ricevere dati in background. Un\'app in uso può accedere ai dati, ma potrebbe farlo con meno frequenza. Esempio: le immagini non vengono visualizzate finché non le tocchi."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Attivare Risparmio dati?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"Attiva"</string>
@@ -1976,10 +1973,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> non è al momento disponibile. Viene gestita tramite <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"Scopri di più"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Riattiva app"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"Attivare le app di lavoro?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"Attiva l\'accesso alle app di lavoro e alle notifiche"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Attiva"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"L\'app non è disponibile"</string>
<string name="app_blocked_message" msgid="542972921087873023">"L\'app <xliff:g id="APP_NAME">%1$s</xliff:g> non è al momento disponibile."</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 9f705fb..b43fb55 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -615,14 +615,14 @@
<string-array name="fingerprint_error_vendor">
</string-array>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"סמל טביעת אצבע"</string>
- <string name="permlab_manageFace" msgid="4569549381889283282">"ניהול החומרה לשחרור נעילה על ידי זיהוי פנים"</string>
+ <string name="permlab_manageFace" msgid="4569549381889283282">"ניהול החומרה לפתיחה ע\"י זיהוי הפנים"</string>
<string name="permdesc_manageFace" msgid="6204569688492710471">"מאפשרת לאפליקציה להפעיל שיטות להוספה ומחיקה של תבניות פנים שבהן ייעשה שימוש."</string>
- <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"שימוש בחומרה לשחרור נעילה על ידי זיהוי פנים"</string>
- <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"מאפשרת לאפליקציה להשתמש בחומרה לשחרור נעילה על ידי זיהוי פנים לצורך אימות"</string>
- <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"שחרור נעילה על ידי זיהוי פנים"</string>
+ <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"שימוש בחומרה לפתיחה ע\"י זיהוי הפנים"</string>
+ <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"מאפשרת לאפליקציה להשתמש בחומרה לפתיחה ע\"י זיהוי הפנים"</string>
+ <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"פתיחה ע\"י זיהוי הפנים"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"יש לבצע סריקה חוזרת של הפנים שלך"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"לשיפור הזיהוי יש לסרוק מחדש את הפנים שלך"</string>
- <string name="face_setup_notification_title" msgid="550617822603450009">"הגדרת שחרור נעילה על ידי זיהוי פנים"</string>
+ <string name="face_setup_notification_title" msgid="550617822603450009">"הגדרה של פתיחה ע\"י זיהוי הפנים"</string>
<string name="face_setup_notification_content" msgid="5463999831057751676">"יש להביט בטלפון כדי לבטל את נעילתו"</string>
<string name="fingerprint_setup_notification_title" msgid="2002630611398849495">"אפשר להגדיר דרכים נוספות לביטול נעילה"</string>
<string name="fingerprint_setup_notification_content" msgid="205578121848324852">"יש להקיש כדי להוסיף טביעת אצבע"</string>
@@ -649,18 +649,18 @@
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="5085202213036026288">"לא ניתן לאמת את הפנים. החומרה לא זמינה."</string>
- <string name="face_error_timeout" msgid="522924647742024699">"יש לנסות שוב את שחרור הנעילה על ידי זיהוי פנים."</string>
+ <string name="face_error_timeout" msgid="522924647742024699">"יש לנסות שוב את הפתיחה ע\"י זיהוי הפנים."</string>
<string name="face_error_no_space" msgid="5649264057026021723">"לא ניתן לאחסן נתוני פנים חדשים. תחילה יש למחוק את הנתונים הישנים."</string>
<string name="face_error_canceled" msgid="2164434737103802131">"הפעולה לאימות הפנים בוטלה."</string>
- <string name="face_error_user_canceled" msgid="8553045452825849843">"שחרור הנעילה על ידי זיהוי פנים בוטל על ידי המשתמש."</string>
+ <string name="face_error_user_canceled" msgid="8553045452825849843">"פתיחה ע\"י זיהוי הפנים בוטל על ידי המשתמש."</string>
<string name="face_error_lockout" msgid="7864408714994529437">"יותר מדי ניסיונות. יש לנסות שוב מאוחר יותר."</string>
- <string name="face_error_lockout_permanent" msgid="8277853602168960343">"יותר מדי ניסיונות. שחרור נעילה על ידי זיהוי פנים מושבת."</string>
+ <string name="face_error_lockout_permanent" msgid="8277853602168960343">"יותר מדי ניסיונות. \'פתיחה ע\"י זיהוי הפנים\' מושבת."</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"לא ניתן לאמת את הפנים. יש לנסות שוב."</string>
- <string name="face_error_not_enrolled" msgid="7369928733504691611">"לא הגדרת שחרור נעילה על ידי זיהוי פנים."</string>
- <string name="face_error_hw_not_present" msgid="1070600921591729944">"המכשיר הזה לא תומך בשחרור נעילה על ידי זיהוי פנים."</string>
+ <string name="face_error_not_enrolled" msgid="7369928733504691611">"לא הגדרת פתיחה ע\"י זיהוי הפנים."</string>
+ <string name="face_error_hw_not_present" msgid="1070600921591729944">"המכשיר הזה לא תומך בפתיחה ע\"י זיהוי הפנים."</string>
<string name="face_error_security_update_required" msgid="5076017208528750161">"החיישן מושבת באופן זמני."</string>
<string name="face_name_template" msgid="3877037340223318119">"פנים <xliff:g id="FACEID">%d</xliff:g>"</string>
- <string name="face_app_setting_name" msgid="8130135875458467243">"שחרור נעילה על ידי זיהוי פנים"</string>
+ <string name="face_app_setting_name" msgid="8130135875458467243">"פתיחה ע\"י זיהוי הפנים"</string>
<string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"שימוש בזיהוי פנים או בנעילת מסך"</string>
<string name="face_dialog_default_subtitle" msgid="6620492813371195429">"יש להשתמש באימות פנים כדי להמשיך"</string>
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"יש להשתמש בזיהוי הפנים או בנעילת המסך כדי להמשיך"</string>
@@ -893,7 +893,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"כדאי לנסות שוב"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"כדאי לנסות שוב"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"צריך לבטל את הנעילה כדי שכל התכונות והנתונים יהיו זמינים"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"חרגת ממספר הניסיונות המרבי לשחרור נעילה על ידי זיהוי פנים"</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"חרגת ממספר הניסיונות המרבי לפתיחה ע\"י זיהוי הפנים"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"אין כרטיס SIM"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"אין כרטיס SIM בטאבלט."</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"אין כרטיס SIM במכשיר ה-Android TV."</string>
@@ -963,7 +963,7 @@
<string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"הרחבה של אזור ביטול הנעילה."</string>
<string name="keyguard_accessibility_slide_unlock" msgid="2968195219692413046">"ביטול נעילה באמצעות הסטה."</string>
<string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"ביטול נעילה על ידי שרטוט קו."</string>
- <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"שחרור נעילה על ידי זיהוי פנים."</string>
+ <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"פתיחה ע\"י זיהוי הפנים."</string>
<string name="keyguard_accessibility_pin_unlock" msgid="4020864007967340068">"ביטול נעילה באמצעות קוד אימות."</string>
<string name="keyguard_accessibility_sim_pin_unlock" msgid="4895939120871890557">"ביטול הנעילה של קוד האימות ל-SIM."</string>
<string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"ביטול נעילה של PUK ל-SIM."</string>
@@ -1028,8 +1028,7 @@
<string name="text_copied" msgid="2531420577879738860">"הטקסט הועתק ללוח."</string>
<string name="copied" msgid="4675902854553014676">"ההעתקה בוצעה"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"האפליקציה <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> הודבקה מ-<xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>"</string>
- <!-- no translation found for pasted_from_clipboard (7355790625710831847) -->
- <skip />
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> הודבקה מהלוח שלך"</string>
<string name="pasted_text" msgid="4298871641549173733">"טקסט שהעתקת הודבק על ידי <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>"</string>
<string name="pasted_image" msgid="4729097394781491022">"תמונה שהעתקת הודבקה על ידי <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>"</string>
<string name="pasted_content" msgid="646276353060777131">"התוכן שהעתקת הודבק על ידי <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>"</string>
@@ -1300,14 +1299,10 @@
<string name="android_preparing_apk" msgid="589736917792300956">"המערכת מכינה את <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"מתבצעת הפעלה של אפליקציות."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"תהליך האתחול בשלבי סיום."</string>
- <!-- no translation found for fp_enrollment_powerbutton_intent_title (3385634173366119903) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_message (6582149052513682522) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_positive_button (5963520983910436791) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_negative_button (6465764183480190748) -->
- <skip />
+ <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="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>
@@ -1762,8 +1757,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"שימוש בקיצור הדרך"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"היפוך צבעים"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"תיקון צבעים"</string>
- <!-- no translation found for one_handed_mode_feature_name (2334330034828094891) -->
- <skip />
+ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"מצב שימוש ביד אחת"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"מעומעם במיוחד"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"לחצני עוצמת הקול נלחצו בלחיצה ארוכה. שירות <xliff:g id="SERVICE_NAME">%1$s</xliff:g> הופעל."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"לחצני עוצמת הקול נלחצו בלחיצה ארוכה. שירות <xliff:g id="SERVICE_NAME">%1$s</xliff:g> הושבת."</string>
@@ -1921,10 +1915,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"עודכנה על ידי מנהל המערכת"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"נמחקה על ידי מנהל המערכת"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"אישור"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"התכונה \'חיסכון בסוללה\' מפעילה עיצוב כהה ומגבילה או מכבה פעילות ברקע, חלק מהאפקטים החזותיים, תכונות מסוימות וחלק מהחיבורים לרשתות.\n\n"<annotation id="url">"מידע נוסף"</annotation></string>
+ <string name="battery_saver_description" msgid="8518809702138617167">"התכונה \'חיסכון בסוללה\' מפעילה עיצוב כהה ומגבילה או מכבה פעילות ברקע, חלק מהאפקטים החזותיים, תכונות מסוימות וחלק מהחיבורים לרשתות."</string>
<string name="data_saver_description" msgid="4995164271550590517">"כדי לסייע בהפחתת השימוש בנתונים, חוסך הנתונים (Data Saver) מונע מאפליקציות מסוימות לשלוח או לקבל נתונים ברקע. אפליקציות שבהן נעשה שימוש כרגע יכולות לגשת לנתונים, אבל בתדירות נמוכה יותר. המשמעות היא, למשל, שתמונות יוצגו רק לאחר שמקישים עליהן."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"להפעיל את חוסך הנתונים?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"הפעלה"</string>
@@ -2045,10 +2037,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"האפליקציה <xliff:g id="APP_NAME_0">%1$s</xliff:g> לא זמינה כרגע. אפשר לנהל זאת באפליקציה <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"מידע נוסף"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"ביטול ההשהיה של האפליקציה"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"להפעיל את האפליקציות לעבודה?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"קבלת גישה להתראות ולאפליקציות לעבודה"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"הפעלה"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"האפליקציה לא זמינה"</string>
<string name="app_blocked_message" msgid="542972921087873023">"האפליקציה <xliff:g id="APP_NAME">%1$s</xliff:g> לא זמינה בשלב זה."</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 7238cde..f5a8ba1 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1713,8 +1713,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"ショートカットを使用"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"色反転"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"色補正"</string>
- <!-- no translation found for one_handed_mode_feature_name (2334330034828094891) -->
- <skip />
+ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"片手モード"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"さらに輝度を下げる"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"音量ボタンを長押ししました。<xliff:g id="SERVICE_NAME">%1$s</xliff:g> が ON になりました。"</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"音量ボタンを長押ししました。<xliff:g id="SERVICE_NAME">%1$s</xliff:g> が OFF になりました。"</string>
@@ -1870,10 +1869,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">"OK"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"バッテリー セーバーを有効にすると、ダークテーマが ON になり、バックグラウンド アクティビティ、一部の視覚効果、特定の機能、一部のネットワーク接続が制限されるか OFF になります。\n\n"<annotation id="url">"詳細"</annotation></string>
+ <string name="battery_saver_description" msgid="8518809702138617167">"バッテリー セーバーを有効にすると、ダークテーマが ON になり、バックグラウンド アクティビティ、一部の視覚効果、特定の機能、一部のネットワーク接続が制限されるか OFF になります。"</string>
<string name="data_saver_description" msgid="4995164271550590517">"データセーバーは、一部のアプリによるバックグラウンドでのデータ送受信を停止することでデータ使用量を抑制します。使用中のアプリからデータを送受信することはできますが、その頻度は低くなる場合があります。この影響として、たとえば画像はタップしないと表示されないようになります。"</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"データセーバーを ON にしますか?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"ON にする"</string>
@@ -1976,10 +1973,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"現在、<xliff:g id="APP_NAME_0">%1$s</xliff:g> は使用できません。このアプリの使用は [<xliff:g id="APP_NAME_1">%2$s</xliff:g>] で管理されています。"</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"詳細"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"アプリの一時停止を解除"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"仕事用アプリを ON にしますか?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"仕事用のアプリや通知を利用する"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"ON にする"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"アプリの利用不可"</string>
<string name="app_blocked_message" msgid="542972921087873023">"現在 <xliff:g id="APP_NAME">%1$s</xliff:g> はご利用になれません。"</string>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index a2b337d..bdad7f6 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -613,7 +613,7 @@
<string name="permdesc_manageFace" msgid="6204569688492710471">"საშუალებას აძლევს აპს, დაამატოს და წაშალოს სახეების შაბლონები."</string>
<string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"სახით განბლოკვის აპარატურის გამოყენება"</string>
<string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"საშუალებას აძლევს აპს, ამოცნობისთვის გამოიყენოს სახით განბლოკვის აპარატურა"</string>
- <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"განბლოკვა სახით"</string>
+ <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"სახით განბლოკვა"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"დაარეგისტრირეთ თქვენი სახე ხელახლა"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"ამოცნობის გასაუმჯობესებლად, გთხოვთ, ხელახლა დაარეგისტრიროთ თქვენი სახე"</string>
<string name="face_setup_notification_title" msgid="550617822603450009">"სახით განბლოკვის დაყენება"</string>
@@ -646,16 +646,16 @@
<string name="face_error_timeout" msgid="522924647742024699">"ცადეთ ხელახლა სახით განბლოკვა."</string>
<string name="face_error_no_space" msgid="5649264057026021723">"სახის ახალი მონაცემები ვერ ინახება. ჯერ ძველი წაშალეთ."</string>
<string name="face_error_canceled" msgid="2164434737103802131">"სახის ამოცნობა გაუქმდა."</string>
- <string name="face_error_user_canceled" msgid="8553045452825849843">"განბლოკვა სახით გაუქმდა მომხმარებლის მიერ."</string>
+ <string name="face_error_user_canceled" msgid="8553045452825849843">"სახით განბლოკვა გაუქმდა მომხმარებლის მიერ."</string>
<string name="face_error_lockout" msgid="7864408714994529437">"დაფიქსირდა ბევრი მცდელობა. ცადეთ მოგვიანებით."</string>
<string name="face_error_lockout_permanent" msgid="8277853602168960343">"მეტისმეტად ბევრი მცდელობა იყო. სახით განბლოკვა გათიშულია."</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"სახის დადასტურება ვერ ხერხდება. ცადეთ ხელახლა."</string>
<string name="face_error_not_enrolled" msgid="7369928733504691611">"თქვენ არ დაგიყენებიათ სახით განბლოკვა."</string>
- <string name="face_error_hw_not_present" msgid="1070600921591729944">"განბლოკვა სახით ამ მოწყობილობაზე მხარდაჭერილი არ არის."</string>
+ <string name="face_error_hw_not_present" msgid="1070600921591729944">"სახით განბლოკვა ამ მოწყობილობაზე მხარდაჭერილი არ არის."</string>
<string name="face_error_security_update_required" msgid="5076017208528750161">"სენსორი დროებით გათიშულია."</string>
<string name="face_name_template" msgid="3877037340223318119">"სახე <xliff:g id="FACEID">%d</xliff:g>"</string>
<string name="face_app_setting_name" msgid="8130135875458467243">"გამოიყენეთ სახით განბლოკვა"</string>
- <string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"გამოიყენეთ სახე ან ეკრანის დაბლოკვა"</string>
+ <string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"გამოიყენეთ სახით ან ეკრანის დაბლოკვა"</string>
<string name="face_dialog_default_subtitle" msgid="6620492813371195429">"გასაგრძელებლად გამოიყენეთ თქვენი სახე"</string>
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"გასაგრძელებლად გამოიყენეთ თქვენი სახე ან ეკრანის განბლოკვის ნიმუში"</string>
<string-array name="face_error_vendor">
@@ -887,7 +887,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"კიდევ სცადეთ"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"კიდევ სცადეთ"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"ყველა ფუნქციისა და მონაცემის განბლოკვა"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"სახის ამოცნობით განბლოკვის მცდელობამ დაშვებულ რაოდენობას გადააჭარბა"</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"სახით განბლოკვის მცდელობამ დაშვებულ რაოდენობას გადააჭარბა"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"SIM ბარათი არ არის"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"ტაბლეტში არ დევს SIM ბარათი."</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"თქვენს Android TV მოწყობილობაში SIM ბარათი არ არის."</string>
@@ -957,7 +957,7 @@
<string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"განბლოკვის სივრცის გაშლა."</string>
<string name="keyguard_accessibility_slide_unlock" msgid="2968195219692413046">"გასრიალებით განბლოკვა"</string>
<string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"განბლოკვა ნიმუშით."</string>
- <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"განბლოკვა სახით"</string>
+ <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"სახით განბლოკვა"</string>
<string name="keyguard_accessibility_pin_unlock" msgid="4020864007967340068">"განბლოკვა Pin-ით."</string>
<string name="keyguard_accessibility_sim_pin_unlock" msgid="4895939120871890557">"SIM-ის PIN-კოდით განბლოკვა."</string>
<string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"SIM-ის PUK-კოდით განბლოკვა."</string>
@@ -1022,8 +1022,7 @@
<string name="text_copied" msgid="2531420577879738860">"ტექსტი დაკოპირებულია გაცვლის ბუფერში."</string>
<string name="copied" msgid="4675902854553014676">"დაკოპირდა"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>-დან <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>-ში ჩასმული"</string>
- <!-- no translation found for pasted_from_clipboard (7355790625710831847) -->
- <skip />
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ჩასმულია თქვენი გაცვლის ბუფერიდან"</string>
<string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>-მ(ა) ჩასვა თქვენ მიერ დაკოპირებული ტექსტი"</string>
<string name="pasted_image" msgid="4729097394781491022">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>-მ(ა) ჩასვა თქვენ მიერ დაკოპირებული სურათი"</string>
<string name="pasted_content" msgid="646276353060777131">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>-მ(ა) ჩასვა თქვენ მიერ დაკოპირებული კონტენტი"</string>
@@ -1260,14 +1259,10 @@
<string name="android_preparing_apk" msgid="589736917792300956">"ემზადება <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"აპების ჩართვა"</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"ჩატვირთვის დასასრული."</string>
- <!-- no translation found for fp_enrollment_powerbutton_intent_title (3385634173366119903) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_message (6582149052513682522) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_positive_button (5963520983910436791) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_negative_button (6465764183480190748) -->
- <skip />
+ <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="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>
@@ -1874,10 +1869,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"განახლებულია თქვენი ადმინისტრატორის მიერ"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"წაიშალა თქვენი ადმინისტრატორის მიერ"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"კარგი"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"ბატარეის დამზოგი ჩართავს მუქ თემას და შეზღუდავს ან გამორთავს ფონურ აქტივობას, ზოგიერთ ვიზუალურ ეფექტს, გარკვეულ ფუნქციებსა და ზოგიერთ ქსელთან კავშირს.\n\n"<annotation id="url">"შეიტყვეთ მეტი"</annotation></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>
@@ -1980,10 +1973,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ამჟამად მიუწვდომელია. ის იმართება <xliff:g id="APP_NAME_1">%2$s</xliff:g>-ის მიერ."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"შეიტყვეთ მეტი"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"აპის დაპაუზების გაუქმება"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"გსურთ სამსახურის აპების ჩართვა?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"თქვენი სამსახურის აპებსა და შეტყობინებებზე წვდომის მოპოვება"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"ჩართვა"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"აპი მიუწვდომელია"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ამჟამად მიუწვდომელია."</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index e748545..43fc7b1 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -609,14 +609,14 @@
<string-array name="fingerprint_error_vendor">
</string-array>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Саусақ ізі белгішесі"</string>
- <string name="permlab_manageFace" msgid="4569549381889283282">"Face Unlock жабдығын басқару"</string>
+ <string name="permlab_manageFace" msgid="4569549381889283282">"Бет тану жабдығын басқару"</string>
<string name="permdesc_manageFace" msgid="6204569688492710471">"Қолданбаға пайдаланатын бет үлгілерін енгізу және жою әдістерін шақыруға мүмкіндік береді."</string>
- <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"Face Unlock жабдығын пайдалану"</string>
- <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Аутентификациялау үшін қолданбаға Face Unlock жабдығын пайдалануға рұқсат береді."</string>
- <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Face Unlock"</string>
+ <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"Бет тану жабдығын пайдалану"</string>
+ <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Аутентификациялау үшін қолданбаға бет тану жабдығын пайдалануға рұқсат береді."</string>
+ <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Бет тану"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Бетті қайта тіркеу"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Құрылғы жүзіңізді жақсырақ тануы үшін, бетіңізді қайта тіркеңіз."</string>
- <string name="face_setup_notification_title" msgid="550617822603450009">"Face Unlock функциясын реттеу"</string>
+ <string name="face_setup_notification_title" msgid="550617822603450009">"Бет тану функциясын реттеу"</string>
<string name="face_setup_notification_content" msgid="5463999831057751676">"Телефоныңызға қарап, оның құлпын ашыңыз."</string>
<string name="fingerprint_setup_notification_title" msgid="2002630611398849495">"Құлыпты ашудың басқа тәсілдерін реттеу"</string>
<string name="fingerprint_setup_notification_content" msgid="205578121848324852">"Саусақ ізін қосу үшін түртіңіз."</string>
@@ -643,18 +643,18 @@
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="5085202213036026288">"Бетті тану мүмкін емес. Жабдық қолжетімді емес."</string>
- <string name="face_error_timeout" msgid="522924647742024699">"Face Unlock функциясын қайта қолданып көріңіз."</string>
+ <string name="face_error_timeout" msgid="522924647742024699">"Бет тану функциясын қайта қолданып көріңіз."</string>
<string name="face_error_no_space" msgid="5649264057026021723">"Жаңа бетті сақтау мүмкін емес. Алдымен ескісін жойыңыз."</string>
<string name="face_error_canceled" msgid="2164434737103802131">"Бетті танудан бас тартылды."</string>
- <string name="face_error_user_canceled" msgid="8553045452825849843">"Пайдаланушы Face Unlock функциясынан бас тартты."</string>
+ <string name="face_error_user_canceled" msgid="8553045452825849843">"Пайдаланушы бет тану функциясынан бас тартты."</string>
<string name="face_error_lockout" msgid="7864408714994529437">"Тым көп әрекет жасалды. Кейінірек қайталаңыз."</string>
- <string name="face_error_lockout_permanent" msgid="8277853602168960343">"Тым көп әрекет жасалды. Face Unlock функциясы өшірілді."</string>
+ <string name="face_error_lockout_permanent" msgid="8277853602168960343">"Тым көп әрекет жасалды. Бет тану функциясы өшірілді."</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"Бетті тану мүмкін емес. Әрекетті қайталаңыз."</string>
- <string name="face_error_not_enrolled" msgid="7369928733504691611">"Face Unlock реттелмеді."</string>
- <string name="face_error_hw_not_present" msgid="1070600921591729944">"Бұл құрылғыда Face Unlock функциясы істемейді."</string>
+ <string name="face_error_not_enrolled" msgid="7369928733504691611">"Бет тану реттелмеді."</string>
+ <string name="face_error_hw_not_present" msgid="1070600921591729944">"Бұл құрылғыда бет тану функциясы істемейді."</string>
<string name="face_error_security_update_required" msgid="5076017208528750161">"Датчик уақытша өшірулі."</string>
<string name="face_name_template" msgid="3877037340223318119">"<xliff:g id="FACEID">%d</xliff:g> беті"</string>
- <string name="face_app_setting_name" msgid="8130135875458467243">"Face Unlock функциясын пайдалану"</string>
+ <string name="face_app_setting_name" msgid="8130135875458467243">"Бет тану функциясын пайдалану"</string>
<string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"Face Lock функциясын немесе экран құлпын пайдалану"</string>
<string name="face_dialog_default_subtitle" msgid="6620492813371195429">"Жалғастыру үшін бетіңізді көрсетіңіз."</string>
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Жалғастыру үшін бетті анықтау функциясын немесе экран құлпын пайдаланыңыз."</string>
@@ -887,7 +887,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Қайталап көріңіз"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"Қайталап көріңіз"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"Мүмкіндіктер мен деректер үшін құлыпты ашыңыз"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Бет-әлпет арқылы ашу әрекеттері анықталған шегінен асып кетті"</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Бет тану арқылы ашу әрекеттері анықталған шегінен асып кетті"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"SIM картасы жоқ"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"Планшетте SIM картасы жоқ."</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"Android TV құрылғыңызда SIM картасы жоқ."</string>
@@ -957,7 +957,7 @@
<string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"Ашу аймағын кеңейту."</string>
<string name="keyguard_accessibility_slide_unlock" msgid="2968195219692413046">"Сырғыту арқылы ашу."</string>
<string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"Кескін арқылы ашу."</string>
- <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"Бет-әлпет арқылы ашу."</string>
+ <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"Бет тану."</string>
<string name="keyguard_accessibility_pin_unlock" msgid="4020864007967340068">"Pin арқылы ашу."</string>
<string name="keyguard_accessibility_sim_pin_unlock" msgid="4895939120871890557">"SIM құлпын PIN кодымен ашу"</string>
<string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"SIM құлпын PUK кодымен ашу"</string>
@@ -1022,8 +1022,7 @@
<string name="text_copied" msgid="2531420577879738860">"Мәтін ақпарат алмастыру қорына сақталды."</string>
<string name="copied" msgid="4675902854553014676">"Көшірілді"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> қолданбасынан <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> қолданбасына қойылды."</string>
- <!-- no translation found for pasted_from_clipboard (7355790625710831847) -->
- <skip />
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> қолданбасы буферіңізден алынған деректерді қойды."</string>
<string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> сіз көшірген мәтінді қойды."</string>
<string name="pasted_image" msgid="4729097394781491022">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> сіз көшірген суретті қойды."</string>
<string name="pasted_content" msgid="646276353060777131">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> сіз көшірген мазмұнды қойды."</string>
@@ -1260,14 +1259,10 @@
<string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> дайындалуда."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Қолданбалар іске қосылуда."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Қосуды аяқтауда."</string>
- <!-- no translation found for fp_enrollment_powerbutton_intent_title (3385634173366119903) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_message (6582149052513682522) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_positive_button (5963520983910436791) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_negative_button (6465764183480190748) -->
- <skip />
+ <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="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>
@@ -1718,8 +1713,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Төте жолды пайдалану"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Түс инверсиясы"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Түсті түзету"</string>
- <!-- no translation found for one_handed_mode_feature_name (2334330034828094891) -->
- <skip />
+ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Бір қолмен басқару режимі"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Экранды қарайту"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Пайдаланушы дыбыс деңгейі пернелерін басып ұстап тұрды. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> қосулы."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Дыбыс деңгейі пернелерін басып тұрған соң, <xliff:g id="SERVICE_NAME">%1$s</xliff:g> өшірілді."</string>
@@ -1875,10 +1869,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Әкімші жаңартқан"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Әкімші жойған"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"Жарайды"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"Батареяны үнемдеу режимі қараңғы тақырыпты іске қосады және фондық әрекеттерге, кейбір визуалдық әсерлерге, белгілі бір функциялар мен кейбір желі байланыстарына шектеу қояды немесе оларды өшіреді.\n\n"<annotation id="url">"Толығырақ"</annotation></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>
@@ -1981,10 +1973,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> дәл қазір қолжетімді емес. Ол <xliff:g id="APP_NAME_1">%2$s</xliff:g> арқылы басқарылады."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"Толығырақ"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Қолданбаны қайта қосу"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"Жұмыс қолданбаларын қосасыз ба?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"Жұмыс қолданбалары мен хабарландыруларына рұқсат алу"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Қосу"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"Қолданба қолжетімді емес"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> қазір қолжетімді емес."</string>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index 31f2b50..b5e5102 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -613,7 +613,7 @@
<string name="permdesc_manageFace" msgid="6204569688492710471">"អនុញ្ញាតឱ្យកម្មវិធីប្រើវិធីសាស្ត្រដើម្បីបញ្ចូល និងលុបទម្រង់គំរូផ្ទៃមុខសម្រាប់ប្រើប្រាស់។"</string>
<string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"ប្រើហាតវែរដោះសោតាមទម្រង់មុខ"</string>
<string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"អនុញ្ញាតឱ្យកម្មវិធីប្រើហាតវែរដោះសោតាមទម្រង់មុខសម្រាប់ការផ្ទៀងផ្ទាត់"</string>
- <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"ការដោះសោតាមទម្រង់មុខ"</string>
+ <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"ដោះសោតាមទម្រង់មុខ"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"ស្កេនបញ្ចូលមុខរបស់អ្នកម្ដងទៀត"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"ដើម្បីធ្វើឱ្យការសម្គាល់មុខប្រសើរជាងមុន សូមស្កេនបញ្ចូលមុខរបស់អ្នកម្ដងទៀត"</string>
<string name="face_setup_notification_title" msgid="550617822603450009">"រៀបចំការដោះសោតាមទម្រង់មុខ"</string>
@@ -1713,8 +1713,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"ប្រើប្រាស់ផ្លូវកាត់"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"បញ្ច្រាសពណ៌"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"ការកែពណ៌"</string>
- <!-- no translation found for one_handed_mode_feature_name (2334330034828094891) -->
- <skip />
+ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"មុខងារប្រើដៃម្ខាង"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"ពន្លឺតិចខ្លាំង"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"បានសង្កត់គ្រាប់ចុចកម្រិតសំឡេងជាប់។ បានបើក <xliff:g id="SERVICE_NAME">%1$s</xliff:g>។"</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"បានសង្កត់គ្រាប់ចុចកម្រិតសំឡេងជាប់។ បានបិទ <xliff:g id="SERVICE_NAME">%1$s</xliff:g>។"</string>
@@ -1870,10 +1869,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"ធ្វើបច្ចុប្បន្នភាពដោយអ្នកគ្រប់គ្រងរបស់អ្នក"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"លុបដោយអ្នកគ្រប់គ្រងរបស់អ្នក"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"យល់ព្រម"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"មុខងារសន្សំថ្មបើករចនាប័ទ្មងងឹត និងដាក់កំហិត ឬបិទសកម្មភាពផ្ទៃខាងក្រោយ ឥទ្ធិពលរូបភាពមួយចំនួន មុខងារជាក់លាក់ និងការតភ្ជាប់បណ្ដាញមួយចំនួន។\n\n"<annotation id="url">"ស្វែងយល់បន្ថែម"</annotation></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>
@@ -1976,10 +1973,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> មិនអាចប្រើបានទេនៅពេលនេះ។ វាស្ថិតក្រោមការគ្រប់គ្រងរបស់ <xliff:g id="APP_NAME_1">%2$s</xliff:g> ។"</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"ស្វែងយល់បន្ថែម"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"ឈប់ផ្អាកកម្មវិធី"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"បើកកម្មវិធីការងារឬ?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"ទទួលបានសិទ្ធិចូលប្រើការជូនដំណឹង និងកម្មវិធីការងាររបស់អ្នក"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"បើក"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"មិនអាចប្រើកម្មវិធីនេះបានទេ"</string>
<string name="app_blocked_message" msgid="542972921087873023">"មិនអាចប្រើ <xliff:g id="APP_NAME">%1$s</xliff:g> នៅពេលនេះបានទេ។"</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index f3d0d58..403a76a 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -1022,8 +1022,7 @@
<string name="text_copied" msgid="2531420577879738860">"ಪಠ್ಯವನ್ನು ಕ್ಲಿಪ್ಬೋರ್ಡ್ಗೆ ನಕಲಿಸಲಾಗಿದೆ."</string>
<string name="copied" msgid="4675902854553014676">"ನಕಲಿಸಲಾಗಿದೆ"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ಅನ್ನು <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> ನಿಂದ ಅಂಟಿಸಲಾಗಿದೆ"</string>
- <!-- no translation found for pasted_from_clipboard (7355790625710831847) -->
- <skip />
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ಅನ್ನು ನಿಮ್ಮ ಕ್ಲಿಪ್ಬೋರ್ಡ್ನಿಂದ ಅಂಟಿಸಲಾಗಿದೆ"</string>
<string name="pasted_text" msgid="4298871641549173733">"ನೀವು ನಕಲಿಸಿರುವ ಪಠ್ಯವನ್ನು <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ನಿಂದ ಅಂಟಿಸಲಾಗಿದೆ"</string>
<string name="pasted_image" msgid="4729097394781491022">"ನೀವು ನಕಲಿಸಿರುವ ಚಿತ್ರವನ್ನು <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ನಿಂದ ಅಂಟಿಸಲಾಗಿದೆ"</string>
<string name="pasted_content" msgid="646276353060777131">"ನೀವು ನಕಲಿಸಿರುವ ವಿಷಯವನ್ನು <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ನಿಂದ ಅಂಟಿಸಲಾಗಿದೆ"</string>
@@ -1260,14 +1259,10 @@
<string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> ಸಿದ್ಧಪಡಿಸಲಾಗುತ್ತಿದೆ."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"ಅಪ್ಲಿಕೇಶನ್ಗಳನ್ನು ಪ್ರಾರಂಭಿಸಲಾಗುತ್ತಿದೆ."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"ಬೂಟ್ ಪೂರ್ಣಗೊಳಿಸಲಾಗುತ್ತಿದೆ."</string>
- <!-- no translation found for fp_enrollment_powerbutton_intent_title (3385634173366119903) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_message (6582149052513682522) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_positive_button (5963520983910436791) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_negative_button (6465764183480190748) -->
- <skip />
+ <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="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>
@@ -1718,8 +1713,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"ಶಾರ್ಟ್ಕಟ್ ಬಳಸಿ"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"ಬಣ್ಣ ವಿಲೋಮ"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"ಬಣ್ಣ ತಿದ್ದುಪಡಿ"</string>
- <!-- no translation found for one_handed_mode_feature_name (2334330034828094891) -->
- <skip />
+ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"ಒಂದು ಕೈ ಮೋಡ್"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"ಇನ್ನಷ್ಟು ಮಬ್ಬು"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ವಾಲ್ಯೂಮ್ ಕೀಗಳನ್ನು ಹಿಡಿದುಕೊಳ್ಳಿ. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ಅನ್ನು ಆನ್ ಮಾಡಲಾಗಿದೆ."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"ವಾಲ್ಯೂಮ್ ಕೀಗಳನ್ನು ಹಿಡಿದಿಟ್ಟುಕೊಳ್ಳಲಾಗಿದೆ. <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, ಆಫ್ ಮಾಡಲಾಗಿದೆ."</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index c74eae7..4c3abec 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -609,14 +609,14 @@
<string-array name="fingerprint_error_vendor">
</string-array>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"지문 아이콘"</string>
- <string name="permlab_manageFace" msgid="4569549381889283282">"얼굴인식 잠금해제 하드웨어 관리"</string>
+ <string name="permlab_manageFace" msgid="4569549381889283282">"얼굴 인식 잠금 해제 하드웨어 관리"</string>
<string name="permdesc_manageFace" msgid="6204569688492710471">"사용할 얼굴 템플릿의 추가 및 삭제 메서드를 앱에서 호출하도록 허용합니다."</string>
- <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"얼굴인식 잠금해제 하드웨어 사용"</string>
- <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"앱에서 얼굴인식 잠금해제 하드웨어를 인증에 사용하도록 허용합니다."</string>
- <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"얼굴인식 잠금해제"</string>
+ <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"얼굴 인식 잠금 해제 하드웨어 사용"</string>
+ <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"앱에서 얼굴 인식 잠금 해제 하드웨어를 인증에 사용하도록 허용합니다."</string>
+ <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"얼굴 인식 잠금 해제"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"얼굴 재등록 필요"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"인식률을 개선하려면 얼굴을 다시 등록하세요."</string>
- <string name="face_setup_notification_title" msgid="550617822603450009">"얼굴인식 잠금해제 설정"</string>
+ <string name="face_setup_notification_title" msgid="550617822603450009">"얼굴 인식 잠금 해제 설정"</string>
<string name="face_setup_notification_content" msgid="5463999831057751676">"휴대전화의 화면을 응시하여 잠금 해제할 수 있습니다."</string>
<string name="fingerprint_setup_notification_title" msgid="2002630611398849495">"다른 잠금 해제 방법 설정"</string>
<string name="fingerprint_setup_notification_content" msgid="205578121848324852">"지문을 추가하려면 탭하세요."</string>
@@ -643,18 +643,18 @@
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="5085202213036026288">"얼굴을 확인할 수 없습니다. 하드웨어를 사용할 수 없습니다."</string>
- <string name="face_error_timeout" msgid="522924647742024699">"얼굴인식 잠금해제를 다시 시도해 주세요."</string>
+ <string name="face_error_timeout" msgid="522924647742024699">"얼굴 인식 잠금 해제를 다시 시도해 주세요."</string>
<string name="face_error_no_space" msgid="5649264057026021723">"새 얼굴 데이터를 저장할 수 없습니다. 먼저 기존 얼굴 데이터를 삭제하세요."</string>
<string name="face_error_canceled" msgid="2164434737103802131">"얼굴 인식 작업이 취소되었습니다."</string>
- <string name="face_error_user_canceled" msgid="8553045452825849843">"사용자가 얼굴인식 잠금해제를 취소했습니다."</string>
+ <string name="face_error_user_canceled" msgid="8553045452825849843">"사용자가 얼굴 인식 잠금 해제를 취소했습니다."</string>
<string name="face_error_lockout" msgid="7864408714994529437">"시도 횟수가 너무 많습니다. 나중에 다시 시도하세요."</string>
- <string name="face_error_lockout_permanent" msgid="8277853602168960343">"시도 횟수가 너무 많습니다. 얼굴인식 잠금해제가 사용 중지되었습니다."</string>
+ <string name="face_error_lockout_permanent" msgid="8277853602168960343">"시도 횟수가 너무 많습니다. 얼굴 인식 잠금 해제가 사용 중지되었습니다."</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"얼굴을 확인할 수 없습니다. 다시 시도하세요."</string>
- <string name="face_error_not_enrolled" msgid="7369928733504691611">"얼굴인식 잠금해제를 설정하지 않았습니다."</string>
- <string name="face_error_hw_not_present" msgid="1070600921591729944">"이 기기에서는 얼굴인식 잠금해제가 지원되지 않습니다."</string>
+ <string name="face_error_not_enrolled" msgid="7369928733504691611">"얼굴 인식 잠금 해제를 설정하지 않았습니다."</string>
+ <string name="face_error_hw_not_present" msgid="1070600921591729944">"이 기기에서는 얼굴 인식 잠금 해제가 지원되지 않습니다."</string>
<string name="face_error_security_update_required" msgid="5076017208528750161">"센서가 일시적으로 사용 중지되었습니다."</string>
<string name="face_name_template" msgid="3877037340223318119">"얼굴 <xliff:g id="FACEID">%d</xliff:g>"</string>
- <string name="face_app_setting_name" msgid="8130135875458467243">"얼굴인식 잠금해제 사용"</string>
+ <string name="face_app_setting_name" msgid="8130135875458467243">"얼굴 인식 잠금 해제 사용"</string>
<string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"얼굴 또는 화면 잠금 사용"</string>
<string name="face_dialog_default_subtitle" msgid="6620492813371195429">"계속하려면 얼굴로 인증하세요"</string>
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"계속하려면 얼굴 또는 화면 잠금을 사용하세요"</string>
@@ -887,7 +887,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"다시 시도"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"다시 시도"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"모든 기능 및 데이터 잠금 해제"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"얼굴 인식 잠금해제 최대 시도 횟수를 초과했습니다."</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"얼굴 인식 잠금 해제 최대 시도 횟수를 초과했습니다."</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"SIM 카드가 없습니다."</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"태블릿에 SIM 카드가 없습니다."</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"Android TV 기기에 SIM 카드가 없습니다."</string>
@@ -957,7 +957,7 @@
<string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"잠금 해제 영역 확장"</string>
<string name="keyguard_accessibility_slide_unlock" msgid="2968195219692413046">"슬라이드하여 잠금해제합니다."</string>
<string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"패턴을 사용하여 잠금해제합니다."</string>
- <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"얼굴 인식을 사용하여 잠금해제합니다."</string>
+ <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"얼굴을 인식하여 잠금 해제합니다."</string>
<string name="keyguard_accessibility_pin_unlock" msgid="4020864007967340068">"핀을 사용하여 잠금해제합니다."</string>
<string name="keyguard_accessibility_sim_pin_unlock" msgid="4895939120871890557">"SIM PIN 잠금 해제"</string>
<string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"SIM PUK 잠금 해제"</string>
@@ -1022,8 +1022,7 @@
<string name="text_copied" msgid="2531420577879738860">"텍스트가 클립보드에 복사되었습니다."</string>
<string name="copied" msgid="4675902854553014676">"복사 완료"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> 앱이 <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> 앱에서 복사하여 붙여넣음"</string>
- <!-- no translation found for pasted_from_clipboard (7355790625710831847) -->
- <skip />
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>에서 클립보드 데이터를 붙여넣음"</string>
<string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>에서 복사한 텍스트를 붙여넣음"</string>
<string name="pasted_image" msgid="4729097394781491022">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>에서 복사한 이미지를 붙여넣음"</string>
<string name="pasted_content" msgid="646276353060777131">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>에서 복사한 콘텐츠를 붙여넣음"</string>
@@ -1260,14 +1259,10 @@
<string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> 준비 중..."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"앱을 시작하는 중입니다."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"부팅 완료"</string>
- <!-- no translation found for fp_enrollment_powerbutton_intent_title (3385634173366119903) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_message (6582149052513682522) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_positive_button (5963520983910436791) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_negative_button (6465764183480190748) -->
- <skip />
+ <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="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>
@@ -1718,8 +1713,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"단축키 사용"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"색상 반전"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"색상 보정"</string>
- <!-- no translation found for one_handed_mode_feature_name (2334330034828094891) -->
- <skip />
+ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"한 손 사용 모드"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"더 어둡게"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"볼륨 키를 길게 눌렀습니다. <xliff:g id="SERVICE_NAME">%1$s</xliff:g>이(가) 사용 설정되었습니다."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"볼륨 키를 길게 눌렀습니다. <xliff:g id="SERVICE_NAME">%1$s</xliff:g>이(가) 사용 중지되었습니다."</string>
@@ -1875,10 +1869,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"관리자에 의해 업데이트되었습니다."</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"관리자에 의해 삭제되었습니다."</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"확인"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"절전 기능은 어두운 테마를 사용 설정하고 백그라운드 활동, 일부 시각 효과, 특정 기능 및 일부 네트워크 연결을 제한하거나 사용 중지합니다.\n\n"<annotation id="url">"자세히 알아보기"</annotation></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>
@@ -1981,10 +1973,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g>은(는) 현재 사용할 수 없습니다. <xliff:g id="APP_NAME_1">%2$s</xliff:g>에서 관리하는 앱입니다."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"자세히 알아보기"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"앱 일시중지 해제"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"직장 앱을 사용 설정하시겠습니까?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"직장 앱 및 알림에 액세스하세요."</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"사용 설정"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"앱을 사용할 수 없습니다"</string>
<string name="app_blocked_message" msgid="542972921087873023">"현재 <xliff:g id="APP_NAME">%1$s</xliff:g> 앱을 사용할 수 없습니다."</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index a60bdd5..01d4219 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -609,11 +609,11 @@
<string-array name="fingerprint_error_vendor">
</string-array>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Манжа изинин сүрөтчөсү"</string>
- <string name="permlab_manageFace" msgid="4569549381889283282">"жүзүнөн таануу функциясынын аппараттык камсыздоосун башкаруу"</string>
+ <string name="permlab_manageFace" msgid="4569549381889283282">"жүзүнөн таанып ачуу функциясынын аппараттык камсыздоосун башкаруу"</string>
<string name="permdesc_manageFace" msgid="6204569688492710471">"Колдонмого пайдалануу үчүн жүздүн үлгүлөрүн кошуу жана жок кылуу мүмкүндүгүн берет."</string>
- <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"аппараттык камсыздоо үчүн жүзүнөн таанууну колдонуу"</string>
- <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Колдонмо аныктыкты текшерүүдө Жүзүнөн таануу функциясынын аппараттык камсыздоосун колдонот"</string>
- <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Жүзүнөн таануу"</string>
+ <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"аппараттык камсыздоо үчүн жүзүнөн таанып ачуу функциясын колдонуу"</string>
+ <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Колдонмо аныктыкты текшерүүдө Жүзүнөн таанып ачуу функциясынын аппараттык камсыздоосун колдонот"</string>
+ <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Жүзүнөн таанып ачуу"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Жүзүңүздү кайра таанытыңыз."</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Мыкты таануу үчүн, жүзүңүздү кайра таанытыңыз"</string>
<string name="face_setup_notification_title" msgid="550617822603450009">"Жүзүнөн таанып ачуу функциясын жөндөңүз"</string>
@@ -643,15 +643,15 @@
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="5085202213036026288">"Жүз ырасталбай жатат. Аппараттык камсыздоо жеткиликсиз."</string>
- <string name="face_error_timeout" msgid="522924647742024699">"Жүзүнөн таануу функциясын кайра текшерип көрүңүз."</string>
+ <string name="face_error_timeout" msgid="522924647742024699">"Жүзүнөн таанып ачуу функциясын кайра текшерип көрүңүз."</string>
<string name="face_error_no_space" msgid="5649264057026021723">"Жаңы жүздү сактоо мүмкүн эмес. Адегенде эскисин өчүрүңүз."</string>
<string name="face_error_canceled" msgid="2164434737103802131">"Жүздүн аныктыгын текшерүү жокко чыгарылды."</string>
- <string name="face_error_user_canceled" msgid="8553045452825849843">"Жүзүнөн таануу функциясын колдонуучу өчүрүп салды."</string>
+ <string name="face_error_user_canceled" msgid="8553045452825849843">"Жүзүнөн таанып ачуу функциясын колдонуучу өчүрүп салды."</string>
<string name="face_error_lockout" msgid="7864408714994529437">"Өтө көп жолу аракет жасадыңыз. Бир аздан кийин кайталап көрүңүз."</string>
- <string name="face_error_lockout_permanent" msgid="8277853602168960343">"Өтө көп жолу аракет кылдыңыз. Жүзүнөн таануу функциясы өчүрүлдү."</string>
+ <string name="face_error_lockout_permanent" msgid="8277853602168960343">"Өтө көп жолу аракет кылдыңыз. Жүзүнөн таанып ачуу функциясы өчүрүлдү."</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"Жүз ырасталбай жатат. Кайталап көрүңүз."</string>
- <string name="face_error_not_enrolled" msgid="7369928733504691611">"Жүзүнөн таануу функциясын жөндөй элексиз."</string>
- <string name="face_error_hw_not_present" msgid="1070600921591729944">"Жүзүнөн таануу функциясы бул түзмөктө иштебейт."</string>
+ <string name="face_error_not_enrolled" msgid="7369928733504691611">"Жүзүнөн таанып ачуу функциясын жөндөй элексиз."</string>
+ <string name="face_error_hw_not_present" msgid="1070600921591729944">"Жүзүнөн таанып ачуу функциясы бул түзмөктө иштебейт."</string>
<string name="face_error_security_update_required" msgid="5076017208528750161">"Сенсор убактылуу өчүрүлгөн."</string>
<string name="face_name_template" msgid="3877037340223318119">"Жүз <xliff:g id="FACEID">%d</xliff:g>"</string>
<string name="face_app_setting_name" msgid="8130135875458467243">"Жүзүнөн таанып ачууну колдонуу"</string>
@@ -957,7 +957,7 @@
<string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"Бөгөттөн чыгаруу аймагын кеңейтүү."</string>
<string name="keyguard_accessibility_slide_unlock" msgid="2968195219692413046">"Жылмыштырып ачуу."</string>
<string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"Үлгү менен ачуу."</string>
- <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"Жүзүнөн таануу"</string>
+ <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"Жүзүнөн таанып ачуу"</string>
<string name="keyguard_accessibility_pin_unlock" msgid="4020864007967340068">"Пин код менен ачуу."</string>
<string name="keyguard_accessibility_sim_pin_unlock" msgid="4895939120871890557">"SIM-картанын кулпусун PIN-код менен ачуу."</string>
<string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"SIM-картанын кулпусун PUK-код менен ачуу."</string>
@@ -1022,8 +1022,7 @@
<string name="text_copied" msgid="2531420577879738860">"Текст алмашуу буферине көчүрүлдү."</string>
<string name="copied" msgid="4675902854553014676">"Көчүрүлдү"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> колдонмосунан чапталды"</string>
- <!-- no translation found for pasted_from_clipboard (7355790625710831847) -->
- <skip />
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> алмашуу буферинен чапталды"</string>
<string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>: көчүрүлгөн текст чапталды"</string>
<string name="pasted_image" msgid="4729097394781491022">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>: көчүрүлгөн сүрөт чапталды"</string>
<string name="pasted_content" msgid="646276353060777131">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>: көчүрүлгөн мазмун чапталды"</string>
@@ -1260,14 +1259,10 @@
<string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> даярдалууда."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Колдонмолорду иштетип баштоо"</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Жүктөлүүдө"</string>
- <!-- no translation found for fp_enrollment_powerbutton_intent_title (3385634173366119903) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_message (6582149052513682522) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_positive_button (5963520983910436791) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_negative_button (6465764183480190748) -->
- <skip />
+ <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="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>
@@ -1718,8 +1713,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Кыска жолду колдонуу"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Түстү инверсиялоо"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Түсүн тууралоо"</string>
- <!-- no translation found for one_handed_mode_feature_name (2334330034828094891) -->
- <skip />
+ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Бир колдуу режим"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Кошумча караңгылатуу"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Үндү катуулатуу/акырындатуу баскычтары басылып, <xliff:g id="SERVICE_NAME">%1$s</xliff:g> күйгүзүлдү."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Үндү катуулатуу/акырындатуу баскычтары басылып, <xliff:g id="SERVICE_NAME">%1$s</xliff:g> өчүрүлдү."</string>
@@ -1875,10 +1869,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Администраторуңуз жаңыртып койгон"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Администраторуңуз жок кылып салган"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ЖАРАЙТ"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"Батареяны үнөмдөгүч режиминде Караңгы тема күйгүзүлүп, фондогу аракеттер, айрым визуалдык эффекттер, белгилүү бир функциялар жана айрым тармакка туташуулар чектелип же өчүрүлөт.\n\n"<annotation id="url">"Кеңири маалымат"</annotation></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>
@@ -1981,10 +1973,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> колдонмосу учурда жеткиликсиз. Анын жеткиликтүүлүгү <xliff:g id="APP_NAME_1">%2$s</xliff:g> тарабынан башкарылат."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"Кеңири маалымат"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Колдонмону иштетүү"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"Жумуш колдонмолору күйгүзүлсүнбү?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"Жумуш колдонмолоруңузга жана билдирмелериңизге мүмкүнчүлүк алыңыз"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Күйгүзүү"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"Колдонмо учурда жеткиликсиз"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> учурда жеткиликсиз"</string>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index 667057f3..d8c0ef1 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -611,7 +611,7 @@
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"ໄອຄອນລາຍນິ້ວມື"</string>
<string name="permlab_manageFace" msgid="4569549381889283282">"ຈັດການຮາດແວປົດລັອກດ້ວຍໜ້າ"</string>
<string name="permdesc_manageFace" msgid="6204569688492710471">"ອະນຸຍາດໃຫ້ແອັບເປີດວິທີການຕ່າງໆເພື່ອເພີ່ມ ແລະ ລຶບແມ່ແບບໃບໜ້າສຳລັບການນຳໃຊ້."</string>
- <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"ໃຊ້ຮາດແວການປົດລັອກໃບໜ້າ"</string>
+ <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"ໃຊ້ຮາດແວການປົດລັອກດ້ວຍໜ້າ"</string>
<string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"ອະນຸຍາດໃຫ້ແອັບໃຊ້ຮາດແວການປົດລັອກດ້ວຍໜ້າເພື່ອພິສູດຢືນຢັນ"</string>
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"ປົດລັອກດ້ວຍໜ້າ"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"ລົງທະບຽນໃບໜ້າຂອງທ່ານຄືນໃໝ່"</string>
@@ -1869,10 +1869,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"ຖືກອັບໂຫລດໂດຍຜູ້ເບິ່ງແຍງລະບົບຂອງທ່ານ"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"ຖືກລຶບອອກໂດຍຜູ້ເບິ່ງແຍງລະບົບຂອງທ່ານ"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ຕົກລົງ"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"ຕົວປະຢັດແບັດເຕີຣີຈະເປີດໃຊ້ຮູບແບບສີສັນມືດ ແລະ ຈຳກັດ ຫຼື ປິດການເຄື່ອນໄຫວໃນພື້ນຫຼັງ, ເອັບເຟັກທາງພາບຈຳນວນໜຶ່ງ, ຄຸນສົມບັດບາງຢ່າງ ແລະ ການເຊື່ອມຕໍ່ເຄືອຂ່າຍບາງອັນ.\n\n"<annotation id="url">"ສຶກສາເພີ່ມເຕີມ"</annotation></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>
@@ -1975,10 +1973,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ບໍ່ສາມາດໃຊ້ໄດ້ໃນຕອນນີ້. ມັນຖືກຈັດການໂດຍ <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"ສຶກສາເພີ່ມເຕີມ"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"ຍົກເລີກການຢຸດແອັບຊົ່ວຄາວ"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"ເປີດໃຊ້ແອັບບ່ອນເຮັດວຽກບໍ?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"ຮັບສິດເຂົ້າເຖິງແອັບບ່ອນເຮັດວຽກ ແລະ ການແຈ້ງເຕືອນຂອງທ່ານ"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"ເປີດ"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"ແອັບບໍ່ສາມາດໃຊ້ໄດ້"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ບໍ່ສາມາດໃຊ້ໄດ້ໃນຕອນນີ້."</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 75facc1..e7b019f 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1757,8 +1757,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Naudoti spartųjį klavišą"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Spalvų inversija"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Spalvų taisymas"</string>
- <!-- no translation found for one_handed_mode_feature_name (2334330034828094891) -->
- <skip />
+ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Vienos rankos režimas"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Itin blanku"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Laikomi garsumo klavišai. „<xliff:g id="SERVICE_NAME">%1$s</xliff:g>“ įjungta."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Laikomi garsumo klavišai. „<xliff:g id="SERVICE_NAME">%1$s</xliff:g>“ išjungta."</string>
@@ -1916,10 +1915,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Atnaujino administratorius"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Ištrynė administratorius"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"Gerai"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"Akumuliatoriaus tausojimo priemonė įjungia tamsiąją temą ir apriboja arba išjungia veiklą fone, kai kuriuos vaizdinius efektus, tam tikras funkcijas bei kai kuriuos tinklo ryšius.\n\n"<annotation id="url">"Sužinokite daugiau"</annotation></string>
+ <string name="battery_saver_description" msgid="8518809702138617167">"Akumuliatoriaus tausojimo priemonė įjungia tamsiąją temą ir apriboja arba išjungia veiklą fone, kai kuriuos vaizdinius efektus, tam tikras funkcijas bei kai kuriuos tinklo ryšius."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Kad padėtų sumažinti duomenų naudojimą, Duomenų taupymo priemonė neleidžia kai kurioms programoms siųsti ar gauti duomenų fone. Šiuo metu naudojama programa gali pasiekti duomenis, bet tai bus daroma rečiau. Tai gali reikšti, kad, pvz., vaizdai nebus pateikiami, jei jų nepaliesite."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Įj. Duomenų taupymo priemonę?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"Įjungti"</string>
@@ -2040,10 +2037,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"Programa „<xliff:g id="APP_NAME_0">%1$s</xliff:g>“ šiuo metu nepasiekiama. Tai tvarkoma naudojant programą „<xliff:g id="APP_NAME_1">%2$s</xliff:g>“."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"Sužinoti daugiau"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Atšaukti programos pristabdymą"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"Įjungti darbo programas?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"Pasiekite darbo programas ir pranešimus"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Įjungti"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"Programa nepasiekiama."</string>
<string name="app_blocked_message" msgid="542972921087873023">"Programa „<xliff:g id="APP_NAME">%1$s</xliff:g>“ šiuo metu nepasiekiama."</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index dbbf427..429a8b0 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1025,8 +1025,7 @@
<string name="text_copied" msgid="2531420577879738860">"Teksts ir kopēts uz starpliktuvi."</string>
<string name="copied" msgid="4675902854553014676">"Nokopēts"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"Lietotnē <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> tika ielīmēti dati no lietotnes <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>."</string>
- <!-- no translation found for pasted_from_clipboard (7355790625710831847) -->
- <skip />
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"Lietotne <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ielīmēja datus no starpliktuves."</string>
<string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ielīmēja jūsu nokopēto tekstu"</string>
<string name="pasted_image" msgid="4729097394781491022">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ielīmēja jūsu nokopēto attēlu"</string>
<string name="pasted_content" msgid="646276353060777131">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ielīmēja jūsu nokopēto saturu"</string>
@@ -1280,14 +1279,10 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Notiek lietotnes <xliff:g id="APPNAME">%1$s</xliff:g> sagatavošana."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Notiek lietotņu palaišana."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Tiek pabeigta sāknēšana."</string>
- <!-- no translation found for fp_enrollment_powerbutton_intent_title (3385634173366119903) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_message (6582149052513682522) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_positive_button (5963520983910436791) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_negative_button (6465764183480190748) -->
- <skip />
+ <string name="fp_enrollment_powerbutton_intent_title" msgid="3385634173366119903">"Vai izslēgt ekrānu?"</string>
+ <string name="fp_enrollment_powerbutton_intent_message" msgid="6582149052513682522">"Iestatot pirksta nospiedumu, jūs nospiedāt barošanas pogu.\n\nTādējādi parasti tiek izslēgts ekrāns."</string>
+ <string name="fp_enrollment_powerbutton_intent_positive_button" msgid="5963520983910436791">"Izslēgt"</string>
+ <string name="fp_enrollment_powerbutton_intent_negative_button" msgid="6465764183480190748">"Atcelt"</string>
<string name="heavy_weight_notification" msgid="8382784283600329576">"<xliff:g id="APP">%1$s</xliff:g> darbojas"</string>
<string name="heavy_weight_notification_detail" msgid="6802247239468404078">"Pieskarieties, lai atgrieztos spēlē"</string>
<string name="heavy_weight_switcher_title" msgid="3861984210040100886">"Spēles izvēlēšanās"</string>
@@ -1740,8 +1735,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Izmantot saīsni"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Krāsu inversija"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Krāsu korekcija"</string>
- <!-- no translation found for one_handed_mode_feature_name (2334330034828094891) -->
- <skip />
+ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Vienas rokas režīms"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Papildu aptumšošana"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Turējāt nospiestas skaļuma pogas. Pakalpojums <xliff:g id="SERVICE_NAME">%1$s</xliff:g> tika ieslēgts."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Turējāt nospiestas skaļuma pogas. Pakalpojums <xliff:g id="SERVICE_NAME">%1$s</xliff:g> tika izslēgts."</string>
@@ -1898,10 +1892,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Atjaunināja administrators"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Dzēsa administrators"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"Labi"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"Akumulatora enerģijas taupīšanas režīmā tiek ieslēgts tumšais motīvs un tiek ierobežotas vai izslēgtas darbības fonā, daži vizuālie efekti, noteiktas funkcijas un noteikti tīkla savienojumi.\n\n"<annotation id="url">"Uzzināt vairāk"</annotation></string>
+ <string name="battery_saver_description" msgid="8518809702138617167">"Akumulatora enerģijas taupīšanas režīmā tiek ieslēgts tumšais motīvs un tiek ierobežotas vai izslēgtas darbības fonā, daži vizuālie efekti, noteiktas funkcijas un noteikti tīkla savienojumi."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Lai samazinātu datu lietojumu, datu lietojuma samazinātājs neļauj dažām lietotnēm fonā nosūtīt vai saņemt datus. Lietotne, kuru pašlaik izmantojat, var piekļūt datiem, bet, iespējams, piekļūs tiem retāk (piemēram, attēli tiks parādīti tikai tad, kad tiem pieskarsieties)."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Vai ieslēgt datu lietojuma samazinātāju?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"Ieslēgt"</string>
@@ -2013,10 +2005,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> pašlaik nav pieejama. Šo darbību pārvalda <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"Uzzināt vairāk"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Atsākt lietotnes darbību"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"Vai ieslēgt darba lietotnes?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"Iegūstiet piekļuvi darba lietotnēm un paziņojumiem"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Ieslēgt"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"Lietotne nav pieejama"</string>
<string name="app_blocked_message" msgid="542972921087873023">"Lietotne <xliff:g id="APP_NAME">%1$s</xliff:g> pašlaik nav pieejama."</string>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 876f522..41ce969 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -887,7 +887,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Обидете се повторно"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"Обидете се повторно"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"Отклучи за сите функции и податоци"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Максималниот број обиди на отклучување со лице е надминат"</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Максималниот број обиди на отклучување со лик е надминат"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"Нема SIM картичка"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"Во таблетот нема SIM картичка."</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"Нема SIM-картичка во вашиот уред Android TV."</string>
@@ -1713,8 +1713,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Користи кратенка"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Инверзија на бои"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Корекција на бои"</string>
- <!-- no translation found for one_handed_mode_feature_name (2334330034828094891) -->
- <skip />
+ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Режим со една рака"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Дополнително затемнување"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Ги задржавте копчињата за јачина на звук. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> е вклучена."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Ги задржавте копчињата за јачина на звук. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> е исклучена."</string>
@@ -1870,10 +1869,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Ажурирано од администраторот"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Избришано од администраторот"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"Во ред"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"„Штедачот на батерија“ вклучува темна тема и ја ограничува или исклучува активноста во заднина, некои визуелни ефекти, одредени функции и некои мрежни врски.\n\n"<annotation id="url">"Дознајте повеќе"</annotation></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>
@@ -1976,10 +1973,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"Апликацијата <xliff:g id="APP_NAME_0">%1$s</xliff:g> не е достапна во моментов. Со ова управува <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"Дознај повеќе"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Прекини ја паузата"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"Да се вклучат работни апликации?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"Добијте пристап до вашите работни апликации и известувања"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Вклучи"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"Апликацијата не е достапна"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> не е достапна во моментов."</string>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index 5448be5..715cd8d 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -611,12 +611,12 @@
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"ഫിംഗർപ്രിന്റ് ഐക്കൺ"</string>
<string name="permlab_manageFace" msgid="4569549381889283282">"മുഖം തിരിച്ചറിഞ്ഞുള്ള അൺലോക്ക് ഹാർഡ്വെയർ മാനേജ് ചെയ്യുക"</string>
<string name="permdesc_manageFace" msgid="6204569688492710471">"ഉപയോഗിക്കാനായി, മുഖത്തിന്റെ ടെംപ്ലേറ്റുകൾ ചേർക്കാനും ഇല്ലാതാക്കാനുമുള്ള രീതികൾ അഭ്യർത്ഥിക്കാൻ ആപ്പിനെ അനുവദിക്കുന്നു."</string>
- <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"മുഖം തിരിച്ചറിഞ്ഞുള്ള അൺലോക്ക് ഹാർഡ്വെയർ ഉപയോഗിക്കുക"</string>
- <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"പരിശോധിച്ചുറപ്പിക്കാൻ മുഖം തിരിച്ചറിഞ്ഞുള്ള അൺലോക്ക് ഹാർഡ്വെയർ ഉപയോഗിക്കാൻ അനുവദിക്കുന്നു"</string>
- <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"മുഖം തിരിച്ചറിഞ്ഞുള്ള അൺലോക്ക്"</string>
+ <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"ഫെയ്സ് അൺലോക്ക് ഹാർഡ്വെയർ ഉപയോഗിക്കുക"</string>
+ <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"പരിശോധിച്ചുറപ്പിക്കാൻ ഫെയ്സ് അൺലോക്ക് ഹാർഡ്വെയർ ഉപയോഗിക്കാൻ അനുവദിക്കുന്നു"</string>
+ <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"ഫെയ്സ് അൺലോക്ക്"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"നിങ്ങളുടെ മുഖം വീണ്ടും എൻറോൾ ചെയ്യൂ"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"തിരിച്ചറിയൽ മെച്ചപ്പെടുത്താൻ, നിങ്ങളുടെ മുഖം ദയവായി വീണ്ടും എൻറോൾ ചെയ്യൂ"</string>
- <string name="face_setup_notification_title" msgid="550617822603450009">"മുഖം തിരിച്ചറിഞ്ഞുള്ള അൺലോക്ക് സജ്ജീകരിക്കുക"</string>
+ <string name="face_setup_notification_title" msgid="550617822603450009">"ഫെയ്സ് അൺലോക്ക് സജ്ജീകരിക്കുക"</string>
<string name="face_setup_notification_content" msgid="5463999831057751676">"ഫോണിലേക്ക് നോക്കി അത് അൺലോക്ക് ചെയ്യുക"</string>
<string name="fingerprint_setup_notification_title" msgid="2002630611398849495">"അൺലോക്ക് ചെയ്യുന്നതിനുള്ള കൂടുതൽ വഴികൾ സജ്ജീകരിക്കുക"</string>
<string name="fingerprint_setup_notification_content" msgid="205578121848324852">"ഫിംഗർപ്രിന്റ് ചേർക്കാൻ ടാപ്പ് ചെയ്യുക"</string>
@@ -643,19 +643,19 @@
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="5085202213036026288">"മുഖം പരിശോധിക്കാൻ കഴിയില്ല. ഹാർഡ്വെയർ ലഭ്യമല്ല."</string>
- <string name="face_error_timeout" msgid="522924647742024699">"മുഖം തിരിച്ചറിഞ്ഞുള്ള അൺലോക്ക് വീണ്ടും പരീക്ഷിക്കൂ"</string>
+ <string name="face_error_timeout" msgid="522924647742024699">"ഫെയ്സ് അൺലോക്ക് വീണ്ടും പരീക്ഷിക്കൂ"</string>
<string name="face_error_no_space" msgid="5649264057026021723">"പുതിയ മുഖ ഡാറ്റ സംഭരിക്കാനാകില്ല. ആദ്യം പഴയത് ഇല്ലാതാക്കുക."</string>
<string name="face_error_canceled" msgid="2164434737103802131">"മുഖത്തിന്റെ പ്രവർത്തനം റദ്ദാക്കി."</string>
- <string name="face_error_user_canceled" msgid="8553045452825849843">"ഉപയോക്താവ് മുഖം തിരിച്ചറിഞ്ഞുള്ള അൺലോക്ക് റദ്ദാക്കി"</string>
+ <string name="face_error_user_canceled" msgid="8553045452825849843">"ഉപയോക്താവ് ഫെയ്സ് അൺലോക്ക് റദ്ദാക്കി"</string>
<string name="face_error_lockout" msgid="7864408714994529437">"നിരവധി തവണ ശ്രമിച്ചു. പിന്നീട് വീണ്ടും ശ്രമിക്കുക."</string>
- <string name="face_error_lockout_permanent" msgid="8277853602168960343">"വളരെയധികം ശ്രമങ്ങൾ. മുഖം തിരിച്ചറിഞ്ഞുള്ള അൺലോക്ക് പ്രവർത്തനരഹിതമാക്കി"</string>
+ <string name="face_error_lockout_permanent" msgid="8277853602168960343">"വളരെയധികം ശ്രമങ്ങൾ. ഫെയ്സ് അൺലോക്ക് പ്രവർത്തനരഹിതമാക്കി"</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"മുഖം പരിശോധിക്കാൻ കഴിയില്ല. വീണ്ടും ശ്രമിക്കൂ."</string>
- <string name="face_error_not_enrolled" msgid="7369928733504691611">"മുഖം തിരിച്ചറിഞ്ഞുള്ള അൺലോക്ക് സജ്ജീകരിച്ചില്ല."</string>
- <string name="face_error_hw_not_present" msgid="1070600921591729944">"മുഖം തിരിച്ചറിഞ്ഞുള്ള അൺലോക്ക് ഈ ഉപകരണം പിന്തുണയ്ക്കുന്നില്ല."</string>
+ <string name="face_error_not_enrolled" msgid="7369928733504691611">"ഫെയ്സ് അൺലോക്ക് സജ്ജീകരിച്ചില്ല."</string>
+ <string name="face_error_hw_not_present" msgid="1070600921591729944">"ഫെയ്സ് അൺലോക്ക് ഈ ഉപകരണം പിന്തുണയ്ക്കുന്നില്ല."</string>
<string name="face_error_security_update_required" msgid="5076017208528750161">"സെൻസർ താൽക്കാലികമായി പ്രവർത്തനരഹിതമാക്കി."</string>
<string name="face_name_template" msgid="3877037340223318119">"മുഖം <xliff:g id="FACEID">%d</xliff:g>"</string>
- <string name="face_app_setting_name" msgid="8130135875458467243">"മുഖം തിരിച്ചറിഞ്ഞുള്ള അൺലോക്ക് ഉപയോഗിക്കുക"</string>
- <string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"മുഖം അല്ലെങ്കിൽ സ്ക്രീൻ ലോക്ക് ഉപയോഗിക്കുക"</string>
+ <string name="face_app_setting_name" msgid="8130135875458467243">"ഫെയ്സ് അൺലോക്ക് ഉപയോഗിക്കുക"</string>
+ <string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"ഫെയ്സ് അല്ലെങ്കിൽ സ്ക്രീൻ ലോക്ക് ഉപയോഗിക്കുക"</string>
<string name="face_dialog_default_subtitle" msgid="6620492813371195429">"തുടരാൻ നിങ്ങളുടെ മുഖം ഉപയോഗിക്കുക"</string>
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"തുടരാൻ നിങ്ങളുടെ മുഖം അല്ലെങ്കിൽ സ്ക്രീൻ ലോക്ക് ഉപയോഗിക്കുക"</string>
<string-array name="face_error_vendor">
@@ -957,7 +957,7 @@
<string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"അൺലോക്ക് ഏരിയ വിപുലീകരിക്കുക."</string>
<string name="keyguard_accessibility_slide_unlock" msgid="2968195219692413046">"സ്ലൈഡ് അൺലോക്ക്."</string>
<string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"പാറ്റേൺ അൺലോക്ക്."</string>
- <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"മുഖം തിരിച്ചറിഞ്ഞുള്ള അൺലോക്ക്."</string>
+ <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"ഫെയ്സ് അൺലോക്ക്."</string>
<string name="keyguard_accessibility_pin_unlock" msgid="4020864007967340068">"പിൻ അൺലോക്ക്."</string>
<string name="keyguard_accessibility_sim_pin_unlock" msgid="4895939120871890557">"സിം പിൻ അൺലോക്ക്."</string>
<string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"സിം Puk അൺലോക്ക്."</string>
@@ -1022,8 +1022,7 @@
<string name="text_copied" msgid="2531420577879738860">"ടെക്സ്റ്റ് ക്ലിപ്ബോർഡിലേക്ക് പകർത്തി."</string>
<string name="copied" msgid="4675902854553014676">"പകർത്തി"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> എന്നതിൽ നിന്ന് <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ഒട്ടിച്ചു"</string>
- <!-- no translation found for pasted_from_clipboard (7355790625710831847) -->
- <skip />
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> നിങ്ങളുടെ ക്ലിപ്പ്ബോർഡിൽ നിന്ന് ഒട്ടിച്ചു"</string>
<string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> നിങ്ങൾ പകർത്തിയ ടെക്സ്റ്റ് ഒട്ടിച്ചു"</string>
<string name="pasted_image" msgid="4729097394781491022">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> നിങ്ങൾ പകർത്തിയ ഒരു ചിത്രം ഒട്ടിച്ചു"</string>
<string name="pasted_content" msgid="646276353060777131">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> നിങ്ങൾ പകർത്തിയ ഉള്ളടക്കം ഒട്ടിച്ചു"</string>
@@ -1260,14 +1259,10 @@
<string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> തയ്യാറാക്കുന്നു."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"അപ്ലിക്കേഷനുകൾ ആരംഭിക്കുന്നു."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"ബൂട്ട് ചെയ്യൽ പൂർത്തിയാകുന്നു."</string>
- <!-- no translation found for fp_enrollment_powerbutton_intent_title (3385634173366119903) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_message (6582149052513682522) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_positive_button (5963520983910436791) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_negative_button (6465764183480190748) -->
- <skip />
+ <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="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>
@@ -1718,8 +1713,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"കുറുക്കുവഴി ഉപയോഗിക്കുക"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"വർണ്ണ വിപര്യയം"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"നിറം ക്രമീകരിക്കൽ"</string>
- <!-- no translation found for one_handed_mode_feature_name (2334330034828094891) -->
- <skip />
+ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"ഒറ്റക്കൈ മോഡ്"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"കൂടുതൽ ഡിം ചെയ്യൽ"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"വോളിയം കീകൾ പിടിച്ചു. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ഓണാക്കി."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"വോളിയം കീകൾ അമർത്തിപ്പിടിച്ചു. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ഓഫാക്കി."</string>
@@ -1875,10 +1869,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"നിങ്ങളുടെ അഡ്മിൻ അപ്ഡേറ്റ് ചെയ്യുന്നത്"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"നിങ്ങളുടെ അഡ്മിൻ ഇല്ലാതാക്കുന്നത്"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ശരി"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"ബാറ്ററി ലാഭിക്കൽ ഡാർക്ക് തീം ഓണാക്കുന്നു, പശ്ചാത്തല ആക്റ്റിവിറ്റിയും ചില വിഷ്വൽ ഇഫക്റ്റുകളും ചില ഫീച്ചറുകളും ചില നെറ്റ്വർക്ക് കണക്ഷനുകളും അത് പരിമിതപ്പെടുത്തുകയോ ഓഫാക്കുകയോ ചെയ്യുന്നു.\n\n"<annotation id="url">"കൂടുതലറിയുക"</annotation></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>
@@ -1981,10 +1973,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ഇപ്പോൾ ലഭ്യമല്ല. <xliff:g id="APP_NAME_1">%2$s</xliff:g> ആണ് ഇത് മാനേജ് ചെയ്യുന്നത്."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"കൂടുതലറിയുക"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"ആപ്പ് പുനഃരാംഭിക്കുക"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"ഔദ്യോഗിക ആപ്പുകൾ ഓണാക്കണോ?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"നിങ്ങളുടെ ഔദ്യോഗിക ആപ്പുകളിലേക്കും അറിയിപ്പുകളിലേക്കും ആക്സസ് നേടുക"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"ഓണാക്കുക"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"ആപ്പ് ലഭ്യമല്ല"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ഇപ്പോൾ ലഭ്യമല്ല."</string>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index ab08384..6053a1c 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -609,14 +609,14 @@
<string-array name="fingerprint_error_vendor">
</string-array>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Хурууны хээний дүрс"</string>
- <string name="permlab_manageFace" msgid="4569549381889283282">"царайгаар тайлах техник хангамжийг удирдах"</string>
+ <string name="permlab_manageFace" msgid="4569549381889283282">"царайгаар түгжээ тайлах техник хангамжийг удирдах"</string>
<string name="permdesc_manageFace" msgid="6204569688492710471">"Аппад царайны загварыг ашиглахын тулд нэмэх эсвэл устгах аргыг идэвхжүүлэхийг зөвшөөрдөг."</string>
- <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"царайгаар тайлах техник хангамж ашиглах"</string>
- <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Аппад царайгаар тайлах техник хангамжийг баталгаажуулалтад ашиглахыг зөвшөөрдөг"</string>
- <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Царайгаар тайлах"</string>
+ <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"царайгаар түгжээ тайлах техник хангамж ашиглах"</string>
+ <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Аппад царайгаар түгжээ тайлах техник хангамжийг баталгаажуулалтад ашиглахыг зөвшөөрдөг"</string>
+ <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Царайгаар түгжээ тайлах"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Царайгаа дахин бүртгүүлнэ үү"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Танилтыг сайжруулахын тулд царайгаа дахин бүртгүүлнэ үү"</string>
- <string name="face_setup_notification_title" msgid="550617822603450009">"Царайгаар тайлах онцлогийг тохируулна уу"</string>
+ <string name="face_setup_notification_title" msgid="550617822603450009">"Царайгаар түгжээ тайлах онцлогийг тохируулна уу"</string>
<string name="face_setup_notification_content" msgid="5463999831057751676">"Утас руугаа харж түгжээг нь тайлна уу"</string>
<string name="fingerprint_setup_notification_title" msgid="2002630611398849495">"Түгжээ тайлах илүү олон арга тохируулна уу"</string>
<string name="fingerprint_setup_notification_content" msgid="205578121848324852">"Хурууны хээ нэмэхийн тулд товшино уу"</string>
@@ -643,19 +643,19 @@
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="5085202213036026288">"Царайг бататгаж чадсангүй. Техник хангамж боломжгүй байна."</string>
- <string name="face_error_timeout" msgid="522924647742024699">"Царайгаар тайлахыг дахин оролдоно уу."</string>
+ <string name="face_error_timeout" msgid="522924647742024699">"Царайгаар түгжээ тайлахыг дахин оролдоно уу."</string>
<string name="face_error_no_space" msgid="5649264057026021723">"Царайн шинэ өгөгдлийг хадгалж чадсангүй. Эхлээд хуучин өгөгдлийг устгана уу."</string>
<string name="face_error_canceled" msgid="2164434737103802131">"Царайны үйл ажиллагааг цуцаллаа."</string>
- <string name="face_error_user_canceled" msgid="8553045452825849843">"Хэрэглэгч царайгаар тайлахыг цуцалсан."</string>
+ <string name="face_error_user_canceled" msgid="8553045452825849843">"Хэрэглэгч царайгаар түгжээ тайлахыг цуцалсан."</string>
<string name="face_error_lockout" msgid="7864408714994529437">"Хэт олон удаа оролдлоо. Дараа дахин оролдоно уу."</string>
- <string name="face_error_lockout_permanent" msgid="8277853602168960343">"Хэтэрхий олон удаа оролдлоо. Царайгаар тайлахыг идэвхгүй болголоо."</string>
+ <string name="face_error_lockout_permanent" msgid="8277853602168960343">"Хэтэрхий олон удаа оролдлоо. Царайгаар түгжээ тайлахыг идэвхгүй болголоо."</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"Царайг бататгаж чадсангүй. Дахин оролдоно уу."</string>
- <string name="face_error_not_enrolled" msgid="7369928733504691611">"Та царайгаар тайлахыг тохируулаагүй байна."</string>
- <string name="face_error_hw_not_present" msgid="1070600921591729944">"Царайгаар тайлахыг энэ төхөөрөмж дээр дэмждэггүй."</string>
+ <string name="face_error_not_enrolled" msgid="7369928733504691611">"Та царайгаар түгжээ тайлахыг тохируулаагүй байна."</string>
+ <string name="face_error_hw_not_present" msgid="1070600921591729944">"Царайгаар түгжээ тайлахыг энэ төхөөрөмж дээр дэмждэггүй."</string>
<string name="face_error_security_update_required" msgid="5076017208528750161">"Мэдрэгчийг түр хугацаанд идэвхгүй болгосон."</string>
<string name="face_name_template" msgid="3877037340223318119">"Царай <xliff:g id="FACEID">%d</xliff:g>"</string>
- <string name="face_app_setting_name" msgid="8130135875458467243">"Царайгаар тайлахыг ашиглах"</string>
- <string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"Царай эсвэл дэлгэцийн түгжээ ашиглах"</string>
+ <string name="face_app_setting_name" msgid="8130135875458467243">"Царайгаар түгжээ тайлахыг ашиглах"</string>
+ <string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"Царайгаар түгжээ тайлах эсвэл дэлгэцийн түгжээ ашиглах"</string>
<string name="face_dialog_default_subtitle" msgid="6620492813371195429">"Үргэлжлүүлэхийн тулд царайгаа ашиглана уу"</string>
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Үргэлжлүүлэхийн тулд царай эсвэл дэлгэцийн түгжээгээ ашиглана уу"</string>
<string-array name="face_error_vendor">
@@ -887,7 +887,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Дахин оролдох"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"Дахин оролдох"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"Бүх онцлог, өгөгдлийн түгжээг тайлах"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Нүүрээр түгжээ тайлах оролдлогын тоо дээд хэмжээнээс хэтэрсэн"</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Царайгаар түгжээ тайлах оролдлогын тоо дээд хэмжээнээс хэтэрсэн"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"SIM карт байхгүй"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"Таблет SIM картгүй."</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"Таны Android TV төхөөрөмжид SIM карт алга."</string>
@@ -957,7 +957,7 @@
<string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"Түгжээгүй хэсгийг өргөсгөх."</string>
<string name="keyguard_accessibility_slide_unlock" msgid="2968195219692413046">"Тайлах гулсуулалт."</string>
<string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"Тайлах хээ."</string>
- <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"Царайгаар тайлах"</string>
+ <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"Царайгаар түгжээ тайлах"</string>
<string name="keyguard_accessibility_pin_unlock" msgid="4020864007967340068">"Тайлах пин."</string>
<string name="keyguard_accessibility_sim_pin_unlock" msgid="4895939120871890557">"Sim-н пин кодыг тайлна уу."</string>
<string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"Sim-н Puk кодыг тайлна уу."</string>
@@ -1713,8 +1713,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Товчлол ашиглах"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Өнгө хувиргалт"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Өнгөний засвар"</string>
- <!-- no translation found for one_handed_mode_feature_name (2334330034828094891) -->
- <skip />
+ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Нэг гарын горим"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Хэт бүүдгэр"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Дууны түвшний түлхүүрийг удаан дарсан. <xliff:g id="SERVICE_NAME">%1$s</xliff:g>-г асаалаа."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Дууны түвшний түлхүүрийг удаан дарсан. <xliff:g id="SERVICE_NAME">%1$s</xliff:g>-г унтраалаа."</string>
@@ -1870,10 +1869,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Таны админ шинэчилсэн"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Таны админ устгасан"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ОК"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"Батарей хэмнэгч нь Бараан загварыг асааж, дэвсгэрийн үйл ажиллагаа, зарим визуал эффект, тодорхой онцлогууд болон зарим сүлжээний холболтыг хязгаарлах эсвэл унтраана.\n\n"<annotation id="url">"Нэмэлт мэдээлэл авах"</annotation></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>
@@ -1976,10 +1973,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> одоогоор боломжгүй байна. Үүнийг <xliff:g id="APP_NAME_1">%2$s</xliff:g>-р удирддаг."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"Дэлгэрэнгүй үзэх"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Аппыг түр зогсоохоо болих"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"Ажлын аппуудыг асаах уу?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"Ажлын аппууд болон мэдэгдлүүддээ хандах эрх аваарай"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Асаах"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"Апп боломжгүй байна"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> яг одоо боломжгүй байна."</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index 2e8d6f5..a4c877f 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -887,7 +887,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"पुन्हा प्रयत्न करा"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"पुन्हा प्रयत्न करा"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"सर्व वैशिष्ट्ये आणि डेटासाठी अनलॉक करा"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"कमाल चेहरा अनलॉक प्रयत्न ओलांडले"</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"कमाल फेस अनलॉक प्रयत्न ओलांडले"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"सिम कार्ड नाही"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"टॅब्लेटमध्ये सिम कार्ड नाही."</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"तुमच्या Android TV डिव्हाइसमध्ये सिम कार्ड नाही."</string>
@@ -957,7 +957,7 @@
<string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"अनलॉक क्षेत्र विस्तृत करा."</string>
<string name="keyguard_accessibility_slide_unlock" msgid="2968195219692413046">"स्लाइड अनलॉक."</string>
<string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"पॅटर्न अनलॉक."</string>
- <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"चेहरा अनलॉक."</string>
+ <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"फेस अनलॉक."</string>
<string name="keyguard_accessibility_pin_unlock" msgid="4020864007967340068">"पिन अनलॉक."</string>
<string name="keyguard_accessibility_sim_pin_unlock" msgid="4895939120871890557">"सिम पिन अनलॉक करा"</string>
<string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"सिम PUK अनलॉक करा"</string>
@@ -1022,8 +1022,7 @@
<string name="text_copied" msgid="2531420577879738860">"मजकूर क्लिपबोर्डवर कॉपी केला."</string>
<string name="copied" msgid="4675902854553014676">"कॉपी केले"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> वरून <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> पेस्ट केले"</string>
- <!-- no translation found for pasted_from_clipboard (7355790625710831847) -->
- <skip />
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ने तुमच्या क्लिपबोर्डवरून पेस्ट केले"</string>
<string name="pasted_text" msgid="4298871641549173733">"तुम्ही कॉपी केलेला मजकूर <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ने पेस्ट केला"</string>
<string name="pasted_image" msgid="4729097394781491022">"तुम्ही कॉपी केलेली इमेज <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ने पेस्ट केली"</string>
<string name="pasted_content" msgid="646276353060777131">"तुम्ही कॉपी केलेला आशय <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ने पेस्ट केला"</string>
@@ -1260,14 +1259,10 @@
<string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> तयार करत आहे."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"अॅप्स सुरू करत आहे."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"बूट समाप्त होत आहे."</string>
- <!-- no translation found for fp_enrollment_powerbutton_intent_title (3385634173366119903) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_message (6582149052513682522) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_positive_button (5963520983910436791) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_negative_button (6465764183480190748) -->
- <skip />
+ <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="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>
@@ -1612,7 +1607,7 @@
<string name="activity_chooser_view_see_all" msgid="3917045206812726099">"सर्व पहा"</string>
<string name="activity_chooser_view_dialog_title_default" msgid="8880731437191978314">"ॲक्टिव्हिटी निवडा"</string>
<string name="share_action_provider_share_with" msgid="1904096863622941880">"यांच्यासह शेअर करा"</string>
- <string name="sending" msgid="206925243621664438">"पाठवित आहे..."</string>
+ <string name="sending" msgid="206925243621664438">"पाठवत आहे..."</string>
<string name="launchBrowserDefault" msgid="6328349989932924119">"ब्राउझर लाँच करायचा?"</string>
<string name="SetupCallDefault" msgid="5581740063237175247">"कॉल स्वीकारायचा?"</string>
<string name="activity_resolver_use_always" msgid="5575222334666843269">"नेहमी"</string>
@@ -1718,8 +1713,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"शॉर्टकट वापरा"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"रंगांची उलटापालट"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"रंग सुधारणा"</string>
- <!-- no translation found for one_handed_mode_feature_name (2334330034828094891) -->
- <skip />
+ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"एकहाती मोड"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"आणखी डिम"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"धरून ठेवलेल्या व्हॉल्यूम की. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> सुरू केला आहे."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"धरून ठेवलेल्या व्हॉल्यूम की. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> बंद केले आहे."</string>
@@ -1875,10 +1869,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"आपल्या प्रशासकाने अपडेट केले"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"आपल्या प्रशासकाने हटवले"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ओके"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"बॅटरी सेव्हर गडद थीम सुरू करते आणि बॅकग्राउंड ॲक्टिव्हिटी, काही व्हिज्युअल इफेक्ट, ठरावीक वैशिष्ट्ये व काही नेटवर्क कनेक्शन मर्यादित किंवा बंद करते.\n\n"<annotation id="url">"अधिक जाणून घ्या"</annotation></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>
@@ -1981,10 +1973,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> आत्ता उपलब्ध नाही. हे <xliff:g id="APP_NAME_1">%2$s</xliff:g> कडून व्यवस्थापित केले जाते."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"अधिक जाणून घ्या"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"अॅप उघडा"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"कार्य अॅप्स सुरू करायची का?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"तुमची कार्य ॲप्स आणि सूचना यांचा अॅक्सेस मिळवा"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"सुरू करा"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"ॲप उपलब्ध नाही"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> आता उपलब्ध नाही."</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index d154582..a95b077 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -609,14 +609,14 @@
<string-array name="fingerprint_error_vendor">
</string-array>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikon cap jari"</string>
- <string name="permlab_manageFace" msgid="4569549381889283282">"urus perkakasan wajah buka kunci"</string>
+ <string name="permlab_manageFace" msgid="4569549381889283282">"urus perkakasan buka kunci wajah"</string>
<string name="permdesc_manageFace" msgid="6204569688492710471">"Membenarkan apl menggunakan kaedah untuk menambahkan dan memadamkan templat wajah untuk digunakan."</string>
- <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"gunakan perkakasan wajah buka kunci"</string>
- <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Membenarkan apl menggunakan perkakasan wajah buka kunci untuk pengesahan"</string>
- <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Wajah buka kunci"</string>
+ <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"gunakan perkakasan buka kunci wajah"</string>
+ <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Membenarkan apl menggunakan perkakasan buka kunci wajah untuk pengesahan"</string>
+ <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Buka kunci wajah"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Daftarkan semula wajah anda"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Untuk meningkatkan pengecaman, sila daftarkan semula wajah anda"</string>
- <string name="face_setup_notification_title" msgid="550617822603450009">"Sediakan wajah buka kunci"</string>
+ <string name="face_setup_notification_title" msgid="550617822603450009">"Sediakan buka kunci wajah"</string>
<string name="face_setup_notification_content" msgid="5463999831057751676">"Buka kunci telefon anda dengan melihat telefon anda"</string>
<string name="fingerprint_setup_notification_title" msgid="2002630611398849495">"Sediakan lebih banyak cara untuk membuka kunci"</string>
<string name="fingerprint_setup_notification_content" msgid="205578121848324852">"Ketik untuk menambahkan cap jari"</string>
@@ -643,18 +643,18 @@
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="5085202213036026288">"Tdk dpt sahkan wajah. Perkakasan tidak tersedia."</string>
- <string name="face_error_timeout" msgid="522924647742024699">"Cuba wajah buka kunci sekali lagi."</string>
+ <string name="face_error_timeout" msgid="522924647742024699">"Cuba buka kunci wajah sekali lagi."</string>
<string name="face_error_no_space" msgid="5649264057026021723">"Tdk dpt menyimpan data wajah baharu. Padamkan yg lama dahulu."</string>
<string name="face_error_canceled" msgid="2164434737103802131">"Pengendalian wajah dibatalkan."</string>
- <string name="face_error_user_canceled" msgid="8553045452825849843">"Wajah buka kunci dibatalkan oleh pengguna."</string>
+ <string name="face_error_user_canceled" msgid="8553045452825849843">"Buka kunci wajah dibatalkan oleh pengguna."</string>
<string name="face_error_lockout" msgid="7864408714994529437">"Terlalu banyak percubaan. Cuba sebentar lagi."</string>
- <string name="face_error_lockout_permanent" msgid="8277853602168960343">"Terlalu banyak percubaan. Wajah buka kunci dilumpuhkan."</string>
+ <string name="face_error_lockout_permanent" msgid="8277853602168960343">"Terlalu banyak percubaan. Buka kunci wajah dilumpuhkan."</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"Tidak dapat mengesahkan wajah. Cuba lagi."</string>
- <string name="face_error_not_enrolled" msgid="7369928733504691611">"Anda belum menyediakan wajah buka kunci."</string>
- <string name="face_error_hw_not_present" msgid="1070600921591729944">"Wajah buka kunci tidak disokong pada peranti ini."</string>
+ <string name="face_error_not_enrolled" msgid="7369928733504691611">"Anda belum menyediakan buka kunci wajah."</string>
+ <string name="face_error_hw_not_present" msgid="1070600921591729944">"Buka kunci wajah tidak disokong pada peranti ini."</string>
<string name="face_error_security_update_required" msgid="5076017208528750161">"Penderia dilumpuhkan sementara."</string>
<string name="face_name_template" msgid="3877037340223318119">"Wajah <xliff:g id="FACEID">%d</xliff:g>"</string>
- <string name="face_app_setting_name" msgid="8130135875458467243">"Gunakan wajah buka kunci"</string>
+ <string name="face_app_setting_name" msgid="8130135875458467243">"Gunakan buka kunci wajah"</string>
<string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"Gunakan kunci wajah atau skrin"</string>
<string name="face_dialog_default_subtitle" msgid="6620492813371195429">"Gunakan wajah untuk teruskan"</string>
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Gunakan wajah atau kunci skrin anda untuk meneruskan"</string>
@@ -957,7 +957,7 @@
<string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"Kembangkan bahagian buka kunci."</string>
<string name="keyguard_accessibility_slide_unlock" msgid="2968195219692413046">"Buka kunci luncur."</string>
<string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"Buka kunci corak."</string>
- <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"Wajah Buka Kunci"</string>
+ <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"Buka Kunci Wajah"</string>
<string name="keyguard_accessibility_pin_unlock" msgid="4020864007967340068">"Buka kunci pin."</string>
<string name="keyguard_accessibility_sim_pin_unlock" msgid="4895939120871890557">"Buka kunci Pin Sim."</string>
<string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"Buka kunci Puk Sim."</string>
@@ -1022,8 +1022,7 @@
<string name="text_copied" msgid="2531420577879738860">"Teks disalin ke papan keratan"</string>
<string name="copied" msgid="4675902854553014676">"Disalin"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ditampalkan daripada <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>"</string>
- <!-- no translation found for pasted_from_clipboard (7355790625710831847) -->
- <skip />
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ditampal daripada papan keratan anda"</string>
<string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> telah menampal teks yang anda salin"</string>
<string name="pasted_image" msgid="4729097394781491022">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> telah menampal imej yang anda salin"</string>
<string name="pasted_content" msgid="646276353060777131">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> telah menampal kandungan yang anda salin"</string>
@@ -1260,14 +1259,10 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Menyediakan <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Memulakan apl."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"But akhir."</string>
- <!-- no translation found for fp_enrollment_powerbutton_intent_title (3385634173366119903) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_message (6582149052513682522) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_positive_button (5963520983910436791) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_negative_button (6465764183480190748) -->
- <skip />
+ <string name="fp_enrollment_powerbutton_intent_title" msgid="3385634173366119903">"Matikan skrin?"</string>
+ <string name="fp_enrollment_powerbutton_intent_message" msgid="6582149052513682522">"Semasa menyediakan cap jari anda, anda menekan butang Kuasa.\n\nTindakan ini biasanya mematikan skrin anda."</string>
+ <string name="fp_enrollment_powerbutton_intent_positive_button" msgid="5963520983910436791">"Matikan"</string>
+ <string name="fp_enrollment_powerbutton_intent_negative_button" msgid="6465764183480190748">"Batal"</string>
<string name="heavy_weight_notification" msgid="8382784283600329576">"<xliff:g id="APP">%1$s</xliff:g> dijalankan"</string>
<string name="heavy_weight_notification_detail" msgid="6802247239468404078">"Ketik untuk kembali ke permainan"</string>
<string name="heavy_weight_switcher_title" msgid="3861984210040100886">"Pilih permainan"</string>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index 2054e47..9ecede5 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -219,7 +219,7 @@
<string name="silent_mode" msgid="8796112363642579333">"အသံတိတ်စနစ်"</string>
<string name="turn_on_radio" msgid="2961717788170634233">"wirelessအားဖွင့်မည်"</string>
<string name="turn_off_radio" msgid="7222573978109933360">"wirelessအားပိတ်မည်"</string>
- <string name="screen_lock" msgid="2072642720826409809">"ဖန်သားပြင် လော့ခ်ချခြင်း"</string>
+ <string name="screen_lock" msgid="2072642720826409809">"ဖန်သားပြင် လော့ခ်ချရန်"</string>
<string name="power_off" msgid="4111692782492232778">"စက်ပိတ်ပါ"</string>
<string name="silent_mode_silent" msgid="5079789070221150912">"ဖုန်းမြည်သံပိတ်ထားသည်"</string>
<string name="silent_mode_vibrate" msgid="8821830448369552678">"တုန်ခါခြင်း ဖုန်းမြည်သံ"</string>
@@ -609,14 +609,14 @@
<string-array name="fingerprint_error_vendor">
</string-array>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"လက်ဗွေ သင်္ကေတ"</string>
- <string name="permlab_manageFace" msgid="4569549381889283282">"မျက်နှာမှတ် သော့ဖွင့်ခြင်း စက်ပစ္စည်းကို စီမံခြင်း"</string>
+ <string name="permlab_manageFace" msgid="4569549381889283282">"မျက်နှာပြလော့ခ်ဖွင့်သည့် စက်ပစ္စည်းကို စီမံခြင်း"</string>
<string name="permdesc_manageFace" msgid="6204569688492710471">"အသုံးပြုရန်အတွက် မျက်နှာပုံစံထည့်ရန် (သို့) ဖျက်ရန်နည်းလမ်းကို အက်ပ်အား သုံးခွင့်ပြုသည်။"</string>
- <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"မျက်နှာမှတ် သော့ဖွင့်ခြင်း စက်ပစ္စည်းကို သုံးပါ"</string>
- <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"အထောက်အထားစိစစ်ရန်အတွက် ဤအက်ပ်အား မျက်နှာမှတ်သော့ဖွင့်ခြင်း စက်ပစ္စည်းကိုသုံးခွင့်ပြုသည်"</string>
- <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"မျက်နှာမှတ် သော့ဖွင့်ခြင်း"</string>
+ <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"မျက်နှာပြ လော့ခ်ဖွင့်သည့် စက်ပစ္စည်းကို သုံးပါ"</string>
+ <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"အထောက်အထားစိစစ်ရန်အတွက် ဤအက်ပ်အား မျက်နှာပြ လော့ခ်ဖွင့်ခြင်း စက်ပစ္စည်းကိုသုံးခွင့်ပြုသည်"</string>
+ <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"မျက်နှာပြ လော့ခ်ဖွင့်ခြင်း"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"သင့်မျက်နှာကို စာရင်းပြန်သွင်းပါ"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"ပိုမှတ်မိစေရန် သင့်မျက်နှာကို စာရင်းပြန်သွင်းပါ"</string>
- <string name="face_setup_notification_title" msgid="550617822603450009">"မျက်နှာမှတ် သော့ဖွင့်ခြင်းကို စနစ်ထည့်သွင်းပါ"</string>
+ <string name="face_setup_notification_title" msgid="550617822603450009">"မျက်နှာပြ လော့ခ်ဖွင့်ခြင်း စနစ်ထည့်သွင်းပါ"</string>
<string name="face_setup_notification_content" msgid="5463999831057751676">"သင့်ဖုန်းကိုကြည့်၍ သော့ဖွင့်ပါ"</string>
<string name="fingerprint_setup_notification_title" msgid="2002630611398849495">"သော့ဖွင့်ရန် နောက်ထပ်နည်းလမ်းများကို စနစ်ထည့်သွင်းပါ"</string>
<string name="fingerprint_setup_notification_content" msgid="205578121848324852">"လက်ဗွေထည့်ရန် တို့ပါ"</string>
@@ -643,18 +643,18 @@
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="5085202213036026288">"မျက်နှာကို အတည်ပြု၍ မရပါ။ ဟာ့ဒ်ဝဲ မရနိုင်ပါ။"</string>
- <string name="face_error_timeout" msgid="522924647742024699">"မျက်နှာမှတ် သော့ဖွင့်ခြင်းကို ထပ်စမ်းကြည့်ပါ။"</string>
+ <string name="face_error_timeout" msgid="522924647742024699">"မျက်နှာပြ လော့ခ်ဖွင့်ခြင်းကို ထပ်စမ်းကြည့်ပါ။"</string>
<string name="face_error_no_space" msgid="5649264057026021723">"မျက်နှာဒေတာအသစ် သိမ်း၍မရပါ။ အဟောင်းကို အရင်ဖျက်ပါ။"</string>
<string name="face_error_canceled" msgid="2164434737103802131">"မျက်နှာ ဆောင်ရွက်ခြင်းကို ပယ်ဖျက်လိုက်ပါပြီ။"</string>
- <string name="face_error_user_canceled" msgid="8553045452825849843">"မှတ်နှာမှတ် သော့ဖွင့်ခြင်းကို အသုံးပြုသူက မလုပ်တော့ပါ။"</string>
+ <string name="face_error_user_canceled" msgid="8553045452825849843">"မှတ်နှာပြ လော့ခ်ဖွင့်ခြင်းကို မလုပ်တော့ပါ။"</string>
<string name="face_error_lockout" msgid="7864408714994529437">"အကြိမ်များစွာ စမ်းပြီးပါပြီ။ နောက်မှထပ်စမ်းပါ။"</string>
- <string name="face_error_lockout_permanent" msgid="8277853602168960343">"စမ်းသပ်ကြိမ် များနေပြီ။ မျက်နှာမှတ် သော့ဖွင့်ခြင်းကို ပိတ်လိုက်ပါပြီ။"</string>
+ <string name="face_error_lockout_permanent" msgid="8277853602168960343">"စမ်းသပ်ကြိမ် များနေပြီ။ မျက်နှာပြ လော့ခ်ဖွင့်ခြင်း ပိတ်လိုက်ပါပြီ။"</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"မျက်နှာကို အတည်ပြု၍ မရပါ။ ထပ်စမ်းကြည့်ပါ။"</string>
- <string name="face_error_not_enrolled" msgid="7369928733504691611">"မျက်နှာမှတ် သော့ဖွင့်ခြင်းကို ထည့်သွင်းမထားပါ"</string>
- <string name="face_error_hw_not_present" msgid="1070600921591729944">"ဤစက်ပစ္စည်းတွင် မျက်နှာမှတ် သော့ဖွင့်ခြင်းကို သုံး၍မရပါ။"</string>
+ <string name="face_error_not_enrolled" msgid="7369928733504691611">"မျက်နှာပြ လော့ခ်ဖွင့်ခြင်း ထည့်သွင်းမထားပါ"</string>
+ <string name="face_error_hw_not_present" msgid="1070600921591729944">"ဤစက်ပစ္စည်းတွင် မျက်နှာပြ လော့ခ်ဖွင့်ခြင်းကို သုံး၍မရပါ။"</string>
<string name="face_error_security_update_required" msgid="5076017208528750161">"အာရုံခံကိရိယာကို ယာယီပိတ်ထားသည်။"</string>
<string name="face_name_template" msgid="3877037340223318119">"မျက်နှာ <xliff:g id="FACEID">%d</xliff:g>"</string>
- <string name="face_app_setting_name" msgid="8130135875458467243">"မျက်နှာမှတ်သော့ဖွင့်ခြင်းကို သုံးခြင်း"</string>
+ <string name="face_app_setting_name" msgid="8130135875458467243">"မျက်နှာပြ လော့ခ်ဖွင့်ရန်"</string>
<string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"မျက်နှာမှတ်သော့ဖွင့်ခြင်း (သို့) ဖန်သားပြင်လော့ခ်ချခြင်းကို သုံးခြင်း"</string>
<string name="face_dialog_default_subtitle" msgid="6620492813371195429">"ရှေ့ဆက်ရန် သင့်မျက်နှာကို သုံးပါ"</string>
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"ရှေ့ဆက်ရန် သင်၏ မျက်နှာ (သို့) ဖန်သားပြင်လော့ခ်ကို သုံးပါ"</string>
@@ -887,7 +887,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"ထပ် စမ်းပါ"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"ထပ် စမ်းပါ"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"ဝန်ဆောင်မှုနှင့် ဒေတာအားလုံးအတွက် လော့ခ်ဖွင့်ပါ"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"မျက်မှာမှတ် သော့ဖွင့်ခြင်း ခွင့်ပြုသော အကြိမ်ရေထက် ကျော်လွန်သွားပါပြီ"</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"မျက်မှာပြ လော့ခ်ဖွင့်ခြင်း ခွင့်ပြုသော အကြိမ်ရေထက် ကျော်လွန်သွားပါပြီ"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"ဆင်းကဒ် မရှိပါ"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"တက်ပလက်ထဲတွင်း ဆင်းကဒ် မရှိပါ"</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"သင့် Android TV စက်ပစ္စည်းပေါ်တွင် ဆင်းမ်ကတ်မရှိပါ။"</string>
@@ -957,7 +957,7 @@
<string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"သော့မချထားသာ နယ်ပယ်ကို ချဲ့ပါ"</string>
<string name="keyguard_accessibility_slide_unlock" msgid="2968195219692413046">"ဘေးတိုက်ပွတ်ဆွဲ၍ သော့ဖွင့်ခြင်း"</string>
<string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"ပုံစံဖြင့် သော့ဖွင့်ခြင်း"</string>
- <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"မျက်နှာမှတ် သော့ဖွင့်ခြင်း"</string>
+ <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"မျက်နှာပြ လော့ခ်ဖွင့်ခြင်း"</string>
<string name="keyguard_accessibility_pin_unlock" msgid="4020864007967340068">"ပင်နံပါတ်ဖြင့် သော့ဖွင့်ခြင်း"</string>
<string name="keyguard_accessibility_sim_pin_unlock" msgid="4895939120871890557">"ဆင်းမ်ကဒ် ပင်နံပါတ်လော့ခ်ဖွင့်ပါ။"</string>
<string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"ဆင်းမ်ကဒ် Puk လော့ခ်ဖွင့်ပါ။"</string>
@@ -1022,8 +1022,7 @@
<string name="text_copied" msgid="2531420577879738860">"clipboardထံ စာသားအားကူးယူမည်"</string>
<string name="copied" msgid="4675902854553014676">"မိတ္တူကူးပြီးပါပြီ"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> မှ <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> သို့ ကူးထည့်ထားသည်"</string>
- <!-- no translation found for pasted_from_clipboard (7355790625710831847) -->
- <skip />
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> က ဒေတာကို သင့်ကလစ်ဘုတ်မှ ကူးထည့်ထားသည်"</string>
<string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> က သင်မိတ္တူကူးထားသော စာသားကို ထည့်လိုက်သည်"</string>
<string name="pasted_image" msgid="4729097394781491022">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> က သင်မိတ္တူကူးထားသော ပုံကို ထည့်လိုက်သည်"</string>
<string name="pasted_content" msgid="646276353060777131">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> က သင်မိတ္တူကူးထားသော အကြောင်းအရာကို ထည့်လိုက်သည်"</string>
@@ -1260,14 +1259,10 @@
<string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> အားပြင်ဆင်နေသည်။"</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"အက်ပ်များကို စတင်နေ"</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"လုပ်ငန်းစနစ်ထည့်သွင်း၍ ပြန်လည်စတင်ရန် ပြီးပါပြီ"</string>
- <!-- no translation found for fp_enrollment_powerbutton_intent_title (3385634173366119903) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_message (6582149052513682522) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_positive_button (5963520983910436791) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_negative_button (6465764183480190748) -->
- <skip />
+ <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="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>
@@ -1874,10 +1869,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">"OK"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"‘ဘက်ထရီ အားထိန်း’ က ‘မှောင်သည့် အပြင်အဆင်’ ကို ဖွင့်ပြီး နောက်ခံလုပ်ဆောင်ချက်၊ ပြသမှုဆိုင်ရာ အထူးပြုလုပ်ချက်အချို့၊ ဝန်ဆောင်မှုအချို့နှင့် ကွန်ရက်ချိတ်ဆက်မှုအချို့တို့ကို ကန့်သတ်သည် သို့မဟုတ် ပိတ်သည်။\n\n"<annotation id="url">"ပိုမိုလေ့လာရန်"</annotation></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>
@@ -1980,10 +1973,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ကို လောလောဆယ် မရနိုင်ပါ။ ၎င်းကို <xliff:g id="APP_NAME_1">%2$s</xliff:g> က စီမံထားပါသည်။"</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"ပိုမိုလေ့လာရန်"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"အက်ပ်ကို ခဏမရပ်တော့ရန်"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"အလုပ်သုံးအက်ပ်များ ဖွင့်မလား။"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"သင့်အလုပ်သုံးအက်ပ်နှင့် အကြောင်းကြားချက်များသုံးခွင့် ရယူပါ"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"ဖွင့်ပါ"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"အက်ပ်ကို မရနိုင်ပါ"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ကို ယခု မရနိုင်ပါ။"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index a6f945c..25db688 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -611,7 +611,7 @@
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikon for fingeravtrykk"</string>
<string name="permlab_manageFace" msgid="4569549381889283282">"administrere maskinvare for Ansiktslås"</string>
<string name="permdesc_manageFace" msgid="6204569688492710471">"Lar appen bruke metoder for å legge til og slette ansiktmaler for bruk."</string>
- <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"bruke maskinvare for Ansiktslås"</string>
+ <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"bruk maskinvare for Ansiktslås"</string>
<string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Lar appen bruke maskinvare for Ansiktslås til autentisering"</string>
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Ansiktslås"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Registrer ansiktet ditt på nytt"</string>
@@ -1869,10 +1869,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Oppdatert av administratoren din"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Slettet av administratoren din"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"Batterisparing slår på mørkt tema og begrenser eller slår av bakgrunnsaktivitet, enkelte visuelle effekter, noen funksjoner og noen nettverkstilkoblinger.\n\n"<annotation id="url">"Finn ut mer"</annotation></string>
+ <string name="battery_saver_description" msgid="8518809702138617167">"Batterisparing slår på mørkt tema og begrenser eller slår av bakgrunnsaktivitet, enkelte visuelle effekter, noen funksjoner og noen nettverkstilkoblinger."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Datasparing hindrer noen apper fra å sende og motta data i bakgrunnen, for å redusere dataforbruket. Aktive apper kan bruke data, men kanskje ikke så mye som ellers – for eksempel vises ikke bilder før du trykker på dem."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Vil du slå på Datasparing?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"Slå på"</string>
@@ -1975,10 +1973,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> er ikke tilgjengelig akkurat nå. Dette administreres av <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"Finn ut mer"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Opphev pause for appen"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"Vil du slå på jobbapper?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"Få tilgang til jobbapper og -varsler"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Slå på"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"Appen er ikke tilgjengelig"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> er ikke tilgjengelig for øyeblikket."</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index d986f2c..d94224a 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -476,8 +476,8 @@
<string name="permdesc_callCompanionApp" msgid="8474168926184156261">"एपलाई डिभाइसमा जारी रहेका कलहरू हेर्नुका साथै तिनीहरूलाई गर्ने अनुमति दिनुहोस्। यसमा गरिएका कलहरूको सङ्ख्या र कलहरूको अवस्था जस्ता जानकारी समावेश हुन्छन्।"</string>
<string name="permlab_exemptFromAudioRecordRestrictions" msgid="1164725468350759486">"अडियो रेकर्ड गर्ने कार्यमा लगाइएका प्रतिबन्धहरूबाट छुट दिनुहोस्"</string>
<string name="permdesc_exemptFromAudioRecordRestrictions" msgid="2425117015896871976">"यो एपलाई अडियो रेकर्ड गर्ने कार्यमा लगाइएका प्रतिबन्धहरूबाट छुट दिनुहोस्।"</string>
- <string name="permlab_acceptHandover" msgid="2925523073573116523">"अर्को अनुप्रयोगमा सुरु गरिएको कल जारी राख्नुहोस्"</string>
- <string name="permdesc_acceptHandovers" msgid="7129026180128626870">"यस एपलाई अर्को अनुप्रयोगमा सुरु गरिएको कल जारी राख्ने अनुमति दिन्छ।"</string>
+ <string name="permlab_acceptHandover" msgid="2925523073573116523">"अर्को एपमा सुरु गरिएको कल जारी राख्नुहोस्"</string>
+ <string name="permdesc_acceptHandovers" msgid="7129026180128626870">"यस एपलाई अर्को एपमा सुरु गरिएको कल जारी राख्ने अनुमति दिन्छ।"</string>
<string name="permlab_readPhoneNumbers" msgid="5668704794723365628">"फोन नम्बरहरू पढ्ने"</string>
<string name="permdesc_readPhoneNumbers" msgid="7368652482818338871">"उक्त एपलाई यस डिभाइसको फोन नम्बरहरूमाथि पहुँच राख्न दिनुहोस्।"</string>
<string name="permlab_wakeLock" product="automotive" msgid="1904736682319375676">"कारको स्क्रिन सक्रिय राख्नुहोस्"</string>
@@ -646,7 +646,7 @@
<string name="face_error_timeout" msgid="522924647742024699">"फेरि फेस अनलक प्रयोग गरी हेर्नुहोस्।"</string>
<string name="face_error_no_space" msgid="5649264057026021723">"अनुहारसम्बन्धी नयाँ डेटा भण्डारण गर्न सकिएन। पहिले कुनै पुरानो डेटा मेटाउनुहोस्।"</string>
<string name="face_error_canceled" msgid="2164434737103802131">"अनुहार पहिचान रद्द गरियो।"</string>
- <string name="face_error_user_canceled" msgid="8553045452825849843">"प्रयोगकर्ताले फेस अनलकको कार्य रद्द गर्नुभयो।"</string>
+ <string name="face_error_user_canceled" msgid="8553045452825849843">"प्रयोगकर्ताले फेस अनलक रद्द गर्नुभयो।"</string>
<string name="face_error_lockout" msgid="7864408714994529437">"धेरैपटक प्रयासहरू भए। पछि फेरि प्रयास गर्नुहोस्।"</string>
<string name="face_error_lockout_permanent" msgid="8277853602168960343">"अत्यधिक प्रयासहरू भए। फेस अनलक असक्षम पारियो।"</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"अनुहार पुष्टि गर्न सकिएन। फेरि प्रयास गर्नुहोस्।"</string>
@@ -887,7 +887,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"फेरि प्रयास गर्नुहोस्"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"फेरि प्रयास गर्नुहोस्"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"सबै सुविधाहरू र डेटाका लागि अनलक गर्नुहोस्"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"अत्यधिक मोहडा खोल्ने प्रयासहरू बढी भए।"</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"फेस अनलक प्रयोग गरी अनलक गर्ने प्रयास अत्याधिक धेरै भयो"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"SIM कार्ड छैन"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"ट्याब्लेटमा SIM कार्ड छैन।"</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"तपाईंको Android टिभी डिभाइसमा SIM कार्ड छैन।"</string>
@@ -1009,7 +1009,7 @@
<string name="permdesc_writeHistoryBookmarks" product="tv" msgid="88642768580408561">"एपलाई तपाईंको Android टिभी डिभाइसमा भण्डार गरिएका ब्राउजरको इतिहास र पुस्तक चिन्हहरू परिमार्जन गर्ने अनुमति दिन्छ। यसले एपलाई ब्राउजरको डेटा मेटाउने वा परिमार्जन गर्ने अनुमति दिन सक्छ। ध्यान दिनुहोस्: तेस्रो पक्षीय ब्राउजर वा वेब ब्राउज गर्ने सुविधा प्रदान गर्ने अन्य एपहरूले यो अनुमति लागू गर्न सक्दैनन्।"</string>
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="2245203087160913652">"तपाईँको फोनमा भण्डारण भएको ब्राउजरको इतिहास वा बुकमार्कहरू परिवर्तन गर्नको लागि एपलाई अनुमति दिन्छ। यसले सायद ब्राउजर डेटालाई मेट्न वा परिवर्तन गर्नको लागि एपलाई अनुमति दिन्छ। नोट: वेब ब्राउज गर्ने क्षमतासहितका अन्य एपहरू वा तेस्रो- पक्ष ब्राउजरद्वारा सायद यस अनुमतिलाई लागु गर्न सकिंदैन।"</string>
<string name="permlab_setAlarm" msgid="1158001610254173567">"एउटा आलर्म सेट गर्नुहोस्"</string>
- <string name="permdesc_setAlarm" msgid="2185033720060109640">"स्थापना गरिएको सङ्केत घडी अनुप्रयोगमा सङ्केत समय मिलाउन एपलाई अनुमति दिन्छ। केही सङ्केत घडी एपहरूले यो सुविधा कार्यान्वयन नगर्न सक्छन्।"</string>
+ <string name="permdesc_setAlarm" msgid="2185033720060109640">"स्थापना गरिएको सङ्केत घडी एपमा सङ्केत समय मिलाउन एपलाई अनुमति दिन्छ। केही सङ्केत घडी एपहरूले यो सुविधा कार्यान्वयन नगर्न सक्छन्।"</string>
<string name="permlab_addVoicemail" msgid="4770245808840814471">"भ्वाइसमेल थप गर्नुहोस्"</string>
<string name="permdesc_addVoicemail" msgid="5470312139820074324">"तपाईँको भ्वाइसमेल इनबक्समा सन्देश थप्नको लागि एपलाई अनुमति दिन्छ।"</string>
<string name="permlab_writeGeolocationPermissions" msgid="8605631647492879449">"भूस्थान अनुमतिहरू ब्राउजर परिवर्तन गर्नुहोस्"</string>
@@ -1022,8 +1022,7 @@
<string name="text_copied" msgid="2531420577879738860">"क्लिपबोर्डमा प्रतिलिप गरिएको पाठ।"</string>
<string name="copied" msgid="4675902854553014676">"प्रतिलिपि गरियो"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> मा रहेको डेटा कपी गरी <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> मा पेस्ट गरियो"</string>
- <!-- no translation found for pasted_from_clipboard (7355790625710831847) -->
- <skip />
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ले तपाईंको क्लिपबोर्डमा रहेको जानकारी पेस्ट गरेको छ"</string>
<string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ले तपाईंले कपी गरेको टेक्स्ट पेस्ट गरेको छ"</string>
<string name="pasted_image" msgid="4729097394781491022">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ले तपाईंले कपी गरेको एउटा फोटो पेस्ट गरेको छ"</string>
<string name="pasted_content" msgid="646276353060777131">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ले तपाईंले कपी गरेको सामग्री पेस्ट गरेको छ"</string>
@@ -1260,14 +1259,10 @@
<string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> तयारी गर्दै।"</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"सुरुवात एपहरू।"</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"बुट पुरा हुँदै।"</string>
- <!-- no translation found for fp_enrollment_powerbutton_intent_title (3385634173366119903) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_message (6582149052513682522) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_positive_button (5963520983910436791) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_negative_button (6465764183480190748) -->
- <skip />
+ <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="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>
@@ -1718,8 +1713,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"सर्टकट प्रयोग गर्नुहोस्"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"रङ्ग उल्टाउने सुविधा"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"रङ्ग सच्याउने सुविधा"</string>
- <!-- no translation found for one_handed_mode_feature_name (2334330034828094891) -->
- <skip />
+ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"एक हाते मोड"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"अझै मधुरो"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"तपाईंले भोल्युम बटनहरू थिचिराख्नुभयो। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> अन भयो।"</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"तपाईंले भोल्युम बटनहरू थिचिराख्नुभयो। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> अफ भयो।"</string>
@@ -1875,10 +1869,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"तपाईंका प्रशासकले अद्यावधिक गर्नुभएको"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"तपाईंका प्रशासकले मेट्नुभएको"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ठिक छ"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"ब्याट्री सेभरले अँध्यारो थिम अन गर्छ र ब्याकग्राउन्डमा हुने क्रियाकलाप, केही भिजुअल इफेक्ट, निश्चित सुविधा र केही नेटवर्क कनेक्सनहरू अफ गर्छ वा सीमित रूपमा मात्र चल्न दिन्छ।\n\n"<annotation id="url">"थप जान्नुहोस्"</annotation></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>
@@ -1981,10 +1973,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> अहिले उपलब्ध छैन। यो <xliff:g id="APP_NAME_1">%2$s</xliff:g> द्वारा व्यवस्थित छ।"</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"थप जान्नुहोस्"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"एपको पज हटाउनुहोस्"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"कामसम्बन्धी एपहरू सक्षम पार्ने हो?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"कामसम्बन्धी एप चलाउने र सूचना प्राप्त गर्ने सुविधा अन गर्नुहोस्"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"सक्रिय गर्नुहोस्"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"एप उपलब्ध छैन"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> अहिले उपलब्ध छैन।"</string>
@@ -2074,7 +2064,7 @@
<string name="slice_more_content" msgid="3377367737876888459">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="shortcut_restored_on_lower_version" msgid="9206301954024286063">"या त एपको संस्करण स्तरह्रास गरियो वा यो यस सर्टकटसँग मिल्दो छैन"</string>
<string name="shortcut_restore_not_supported" msgid="4763198938588468400">"अनुप्रयोगले ब्याकअप तथा पुनर्स्थापनालाई समर्थन नगर्ने हुँदा सर्टकट पुनर्स्थापित गर्न सकिएन"</string>
- <string name="shortcut_restore_signature_mismatch" msgid="579345304221605479">"अनुप्रयोगमा प्रयोग गरिने हस्ताक्षर नमिल्ने हुँदा सर्टकट पुनर्स्थापित गर्न सकिएन"</string>
+ <string name="shortcut_restore_signature_mismatch" msgid="579345304221605479">"एपमा प्रयोग गरिने हस्ताक्षर नमिल्ने हुँदा सर्टकट पुनर्स्थापित गर्न सकिएन"</string>
<string name="shortcut_restore_unknown_issue" msgid="2478146134395982154">"सर्टकट पुनर्स्थापित गर्न सकिएन"</string>
<string name="shortcut_disabled_reason_unknown" msgid="753074793553599166">"सर्टकट असक्षम पारिएको छ"</string>
<string name="harmful_app_warning_uninstall" msgid="6472912975664191772">"स्थापना रद्द गर्नु…"</string>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index 15a0531..6ce5f3c 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -609,11 +609,11 @@
<string-array name="fingerprint_error_vendor">
</string-array>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"ଟିପଚିହ୍ନ ଆଇକନ୍"</string>
- <string name="permlab_manageFace" msgid="4569549381889283282">"ଫେସ୍ ଅନ୍ଲକ୍ ହାର୍ଡୱେର୍ ପରିଚାଳନା କରନ୍ତୁ"</string>
+ <string name="permlab_manageFace" msgid="4569549381889283282">"ଫେସ୍ ଅନଲକ୍ ହାର୍ଡୱେର୍ ପରିଚାଳନା କରନ୍ତୁ"</string>
<string name="permdesc_manageFace" msgid="6204569688492710471">"ବ୍ୟବହାର ପାଇଁ ଆପ୍କୁ ଫେସିଆଲ୍ ଟେମ୍ପଲେଟ୍ ଯୋଡିବା ଓ ଡିଲିଟ୍ ର ପଦ୍ଧତି ପାଇଁ ଅନୁମତି ଦିଅନ୍ତୁ।"</string>
- <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"ଫେସ୍ ଅନ୍ଲକ୍ ହାର୍ଡୱେର୍ ବ୍ୟବହାର କରନ୍ତୁ"</string>
- <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"ପ୍ରାମାଣିକତା ପାଇଁ ଫେସ୍ ଅନ୍ଲକ୍ ହାର୍ଡୱେର୍ର ବ୍ୟବହାର ପାଇଁ ଆପ୍କୁ ଅନୁମତି ଦିଅନ୍ତୁ।"</string>
- <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"ଫେସ୍ ଅନ୍ଲକ୍"</string>
+ <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"ଫେସ୍ ଅନଲକ୍ ହାର୍ଡୱେର୍ ବ୍ୟବହାର କରନ୍ତୁ"</string>
+ <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"ପ୍ରମାଣୀକରଣ ପାଇଁ ଫେସ୍ ଅନଲକ୍ ହାର୍ଡୱେର୍ର ବ୍ୟବହାର କରିବା ପାଇଁ ଆପ୍କୁ ଅନୁମତି ଦିଅନ୍ତୁ"</string>
+ <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"ଫେସ୍ ଅନଲକ୍"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"ଆପଣଙ୍କର ମୁହଁ ପୁଣି-ଏନ୍ରୋଲ୍ କରନ୍ତୁ"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"ଚିହ୍ନଟକରଣକୁ ଉନ୍ନତ କରିବା ପାଇଁ, ଦୟାକରି ଆପଣଙ୍କର ମୁହଁ ପୁଣି-ଏନ୍ରୋଲ୍ କରନ୍ତୁ।"</string>
<string name="face_setup_notification_title" msgid="550617822603450009">"ଫେସ୍ ଅନଲକ୍ ସେଟ୍ ଅପ୍ କରନ୍ତୁ"</string>
@@ -643,15 +643,15 @@
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="5085202213036026288">"ମୁହଁ ଚିହ୍ନଟ କରିପାରିଲା ନାହିଁ। ହାର୍ଡୱେୟାର୍ ଉପଲବ୍ଧ ନାହିଁ।"</string>
- <string name="face_error_timeout" msgid="522924647742024699">"ଫେସ୍ ଅନ୍ଲକ୍ ପୁଣି ବ୍ୟବହାର କରି ଦେଖନ୍ତୁ"</string>
+ <string name="face_error_timeout" msgid="522924647742024699">"ଫେସ୍ ଅନଲକ୍ ପୁଣି ବ୍ୟବହାର କରି ଦେଖନ୍ତୁ।"</string>
<string name="face_error_no_space" msgid="5649264057026021723">"ନୂଆ ମୁହଁ ଡାଟା ଷ୍ଟୋର୍ ହେବ ନାହିଁ। ପ୍ରଥମେ ପୁରୁଣାକୁ ଡିଲିଟ୍ କରନ୍ତୁ।"</string>
<string name="face_error_canceled" msgid="2164434737103802131">"ଫେସ୍ର ଅପରେଶନ୍ କ୍ୟାନ୍ସଲ୍ ହୋଇଗଲା"</string>
<string name="face_error_user_canceled" msgid="8553045452825849843">"ଉପଯୋଗକର୍ତ୍ତାଙ୍କ ଦ୍ୱାରା ଫେସ୍ ଅନଲକ୍ ବାତିଲ୍ କରାଯାଇଛି।"</string>
<string name="face_error_lockout" msgid="7864408714994529437">"ବାରମ୍ବାର ଚେଷ୍ଟା। ପରେ ପୁଣିଥରେ ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
- <string name="face_error_lockout_permanent" msgid="8277853602168960343">"ଅତ୍ୟଧିକ ପ୍ରଚେଷ୍ଟା. ଫେସ୍ ଅନ୍ଲକ୍ ଅକ୍ଷମ କରନ୍ତୁ"</string>
+ <string name="face_error_lockout_permanent" msgid="8277853602168960343">"ଅତ୍ୟଧିକ ପ୍ରଚେଷ୍ଟା। ଫେସ୍ ଅନଲକ୍ ଅକ୍ଷମ ହୋଇଛି।"</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"ମୁହଁ ଚିହ୍ନଟ କରିପାରିଲା ନାହିଁ। ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
- <string name="face_error_not_enrolled" msgid="7369928733504691611">"ଆପଣ ଫେସ୍ ଅନ୍ଲକ୍ ସେଟ୍ ଅପ୍ କରିନାହାଁନ୍ତି"</string>
- <string name="face_error_hw_not_present" msgid="1070600921591729944">"ଏହି ଡିଭାଇସ୍ରେ ଫେସ୍ ଅନ୍ଲକ୍ ସମର୍ଥିତ ନୁହେଁ।"</string>
+ <string name="face_error_not_enrolled" msgid="7369928733504691611">"ଆପଣ ଫେସ୍ ଅନଲକ୍ ସେଟ୍ ଅପ୍ କରିନାହାଁନ୍ତି।"</string>
+ <string name="face_error_hw_not_present" msgid="1070600921591729944">"ଏହି ଡିଭାଇସରେ ଫେସ୍ ଅନଲକ୍ ସମର୍ଥିତ ନୁହେଁ।"</string>
<string name="face_error_security_update_required" msgid="5076017208528750161">"ସେନ୍ସରକୁ ଅସ୍ଥାୟୀ ଭାବେ ଅକ୍ଷମ କରାଯାଇଛି।"</string>
<string name="face_name_template" msgid="3877037340223318119">"<xliff:g id="FACEID">%d</xliff:g>ଙ୍କ ଫେସ୍"</string>
<string name="face_app_setting_name" msgid="8130135875458467243">"ଫେସ୍ ଅନଲକ୍ ବ୍ୟବହାର କରନ୍ତୁ"</string>
@@ -887,7 +887,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"ସମସ୍ତ ସୁବିଧା ତଥା ଡାଟା ପାଇଁ ଅନଲକ୍ କରନ୍ତୁ"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"ମାଲିକର ମୁହଁ ଚିହ୍ନି ଅନଲକ୍ କରିବାର ସର୍ବାଧିକ ଧାର୍ଯ୍ୟ ସୀମା ଅତିକ୍ରମ କଲା"</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"ସର୍ବାଧିକ ଫେସ୍ ଅନଲକ୍ ପ୍ରଚେଷ୍ଟା ଅତିକ୍ରମ କରିଛି"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"କୌଣସି SIM କାର୍ଡ ନାହିଁ"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"ଟାବଲେଟ୍ରେ କୌଣସି SIM କାର୍ଡ ନାହିଁ।"</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"ଆପଣଙ୍କର Android TV ଡିଭାଇସ୍ରେ କୌଣସି SIM କାର୍ଡ ନାହିଁ।"</string>
@@ -1713,8 +1713,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"ଶର୍ଟକଟ୍ ବ୍ୟବହାର କରନ୍ତୁ"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"ରଙ୍ଗ ବଦଳାଇବାର ସୁବିଧା"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"ରଙ୍ଗ ସଂଶୋଧନ"</string>
- <!-- no translation found for one_handed_mode_feature_name (2334330034828094891) -->
- <skip />
+ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"ଏକ-ହାତ ମୋଡ୍"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"ଅତିରିକ୍ତ ଡିମ୍"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ଭଲ୍ୟୁମ୍ କୀ\'ଗୁଡ଼ିକୁ ଧରି ରଖାଯାଇଛି। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ଚାଲୁ ହୋଇଛି।"</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"ଭଲ୍ୟୁମ୍ କୀ\'ଗୁଡ଼ିକୁ ଧରି ରଖାଯାଇଛି। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ବନ୍ଦ ହୋଇଛି।"</string>
@@ -1870,10 +1869,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"ଆପଣଙ୍କ ଆଡମିନ୍ ଅପଡେଟ୍ କରିଛନ୍ତି"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"ଆପଣଙ୍କ ଆଡମିନ୍ ଡିଲିଟ୍ କରିଛନ୍ତି"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ଠିକ୍ ଅଛି"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"ବ୍ୟାଟେରୀ ସେଭର୍ ଗାଢ଼ା ଥିମକୁ ଚାଲୁ କରେ ଏବଂ ପୃଷ୍ଠପଟ କାର୍ଯ୍ୟକଳାପ, କିଛି ଭିଜୁଆଲ୍ ଇଫେକ୍ଟ, କିଛି ଫିଚର୍ ଏବଂ କିଛି ନେଟୱାର୍କ ସଂଯୋଗକୁ ସୀମିତ କିମ୍ବା ବନ୍ଦ କରେ।\n\n"<annotation id="url">"ଅଧିକ ଜାଣନ୍ତୁ"</annotation></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>
@@ -1976,10 +1973,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"ବର୍ତ୍ତମାନ <xliff:g id="APP_NAME_0">%1$s</xliff:g> ଉପଲବ୍ଧ ନାହିଁ। ଏହା <xliff:g id="APP_NAME_1">%2$s</xliff:g> ଦ୍ଵାରା ପରିଚାଳିତ ହେଉଛି।"</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"ଅଧିକ ଜାଣନ୍ତୁ"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"ଆପ୍ ଅନପଜ୍ କରନ୍ତୁ"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"ୱାର୍କ ଆପଗୁଡ଼ିକୁ ଚାଲୁ କରିବେ?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"ଆପଣଙ୍କ ୱାର୍କ ଆପ୍ ଏବଂ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକୁ ଆକ୍ସେସ୍ ପାଆନ୍ତୁ"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"ଚାଲୁ କରନ୍ତୁ"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"ଆପ୍ ଉପଲବ୍ଧ ନାହିଁ"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ବର୍ତ୍ତମାନ ଉପଲବ୍ଧ ନାହିଁ।"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 50e1f98..ba4730c 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -609,14 +609,14 @@
<string-array name="fingerprint_error_vendor">
</string-array>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਪ੍ਰਤੀਕ"</string>
- <string name="permlab_manageFace" msgid="4569549381889283282">"ਚਿਹਰਾ ਅਣਲਾਕ ਹਾਰਡਵੇਅਰ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰੋ"</string>
+ <string name="permlab_manageFace" msgid="4569549381889283282">"ਫ਼ੇਸ ਅਣਲਾਕ ਹਾਰਡਵੇਅਰ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰੋ"</string>
<string name="permdesc_manageFace" msgid="6204569688492710471">"ਐਪ ਨੂੰ ਵਰਤਣ ਲਈ ਚਿਹਰਾ ਟੈਮਪਲੇਟ ਸ਼ਾਮਲ ਕਰਨ ਜਾਂ ਮਿਟਾਉਣ ਦੀਆਂ ਵਿਧੀਆਂ ਦੀ ਬੇਨਤੀ ਕਰਨ ਦਿੰਦੀ ਹੈ।"</string>
- <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"ਚਿਹਰਾ ਅਣਲਾਕ ਹਾਰਡਵੇਅਰ ਵਰਤੋ"</string>
- <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"ਐਪ ਨੂੰ ਪ੍ਰਮਾਣੀਕਰਨ ਲਈ ਚਿਹਰਾ ਅਣਲਾਕ ਹਾਰਡਵੇਅਰ ਵਰਤਣ ਦਿੰਦੀ ਹੈ"</string>
- <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"ਚਿਹਰਾ ਅਣਲਾਕ"</string>
+ <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"ਫ਼ੇਸ ਅਣਲਾਕ ਹਾਰਡਵੇਅਰ ਵਰਤੋ"</string>
+ <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"ਐਪ ਨੂੰ ਪ੍ਰਮਾਣੀਕਰਨ ਲਈ ਫ਼ੇਸ ਅਣਲਾਕ ਹਾਰਡਵੇਅਰ ਵਰਤਣ ਦਿੰਦੀ ਹੈ"</string>
+ <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"ਫ਼ੇਸ ਅਣਲਾਕ"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"ਆਪਣਾ ਚਿਹਰਾ ਮੁੜ-ਦਰਜ ਕਰੋ"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"ਪਛਾਣ ਨੂੰ ਬਿਹਤਰ ਬਣਾਉਣ ਲਈ, ਕਿਰਪਾ ਕਰਕੇ ਆਪਣੇ ਚਿਹਰੇ ਨੂੰ ਮੁੜ-ਦਰਜ ਕਰੋ"</string>
- <string name="face_setup_notification_title" msgid="550617822603450009">"ਚਿਹਰਾ ਅਣਲਾਕ ਸੈੱਟਅੱਪ ਕਰੋ"</string>
+ <string name="face_setup_notification_title" msgid="550617822603450009">"ਫ਼ੇਸ ਅਣਲਾਕ ਸੈੱਟਅੱਪ ਕਰੋ"</string>
<string name="face_setup_notification_content" msgid="5463999831057751676">"ਆਪਣੇ ਫ਼ੋਨ ਵੱਲ ਦੇਖ ਕੇ ਇਸਨੂੰ ਅਣਲਾਕ ਕਰੋ"</string>
<string name="fingerprint_setup_notification_title" msgid="2002630611398849495">"ਅਣਲਾਕ ਕਰਨ ਦੇ ਹੋਰ ਤਰੀਕਿਆਂ ਦਾ ਸੈੱਟਅੱਪ ਕਰੋ"</string>
<string name="fingerprint_setup_notification_content" msgid="205578121848324852">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਸ਼ਾਮਲ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ"</string>
@@ -643,19 +643,19 @@
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="5085202213036026288">"ਚਿਹਰੇ ਦੀ ਪੁਸ਼ਟੀ ਨਹੀਂ ਹੋ ਸਕੀ। ਹਾਰਡਵੇਅਰ ਉਪਲਬਧ ਨਹੀਂ।"</string>
- <string name="face_error_timeout" msgid="522924647742024699">"ਚਿਹਰਾ ਅਣਲਾਕ ਦੁਬਾਰਾ ਵਰਤ ਕੇ ਦੇਖੋ।"</string>
+ <string name="face_error_timeout" msgid="522924647742024699">"ਫ਼ੇਸ ਅਣਲਾਕ ਦੁਬਾਰਾ ਵਰਤ ਕੇ ਦੇਖੋ।"</string>
<string name="face_error_no_space" msgid="5649264057026021723">"ਨਵਾਂ ਚਿਹਰਾ ਡਾਟਾ ਸਟੋਰ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ। ਪਹਿਲਾਂ ਪੁਰਾਣਾ ਹਟਾਓ।"</string>
<string name="face_error_canceled" msgid="2164434737103802131">"ਚਿਹਰਾ ਪਛਾਣਨ ਦੀ ਪ੍ਰਕਿਰਿਆ ਰੱਦ ਕੀਤੀ ਗਈ।"</string>
- <string name="face_error_user_canceled" msgid="8553045452825849843">"ਵਰਤੋਂਕਾਰ ਨੇ ਚਿਹਰਾ ਅਣਲਾਕ ਰੱਦ ਕੀਤਾ।"</string>
+ <string name="face_error_user_canceled" msgid="8553045452825849843">"ਵਰਤੋਂਕਾਰ ਨੇ ਫ਼ੇਸ ਅਣਲਾਕ ਰੱਦ ਕੀਤਾ।"</string>
<string name="face_error_lockout" msgid="7864408714994529437">"ਹੱਦੋਂ ਵੱਧ ਕੋਸ਼ਿਸ਼ਾਂ। ਬਾਅਦ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
- <string name="face_error_lockout_permanent" msgid="8277853602168960343">"ਬਹੁਤ ਸਾਰੀਆਂ ਕੋਸ਼ਿਸ਼ਾਂ। ਚਿਹਰਾ ਅਣਲਾਕ ਬੰਦ ਕੀਤਾ ਗਿਆ।"</string>
+ <string name="face_error_lockout_permanent" msgid="8277853602168960343">"ਬਹੁਤ ਸਾਰੀਆਂ ਕੋਸ਼ਿਸ਼ਾਂ। ਫ਼ੇਸ ਅਣਲਾਕ ਬੰਦ ਕੀਤਾ ਗਿਆ।"</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"ਚਿਹਰੇ ਦੀ ਪੁਸ਼ਟੀ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕੀ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
- <string name="face_error_not_enrolled" msgid="7369928733504691611">"ਤੁਸੀਂ ਚਿਹਰਾ ਅਣਲਾਕ ਸੈੱਟਅੱਪ ਨਹੀਂ ਕੀਤਾ ਹੈ।"</string>
- <string name="face_error_hw_not_present" msgid="1070600921591729944">"ਇਸ ਡੀਵਾਈਸ ਵਿੱਚ ਚਿਹਰਾ ਅਣਲਾਕ ਦੀ ਸੁਵਿਧਾ ਨਹੀਂ ਹੈ।"</string>
+ <string name="face_error_not_enrolled" msgid="7369928733504691611">"ਤੁਸੀਂ ਫ਼ੇਸ ਅਣਲਾਕ ਸੈੱਟਅੱਪ ਨਹੀਂ ਕੀਤਾ ਹੈ।"</string>
+ <string name="face_error_hw_not_present" msgid="1070600921591729944">"ਇਸ ਡੀਵਾਈਸ ਵਿੱਚ ਫ਼ੇਸ ਅਣਲਾਕ ਦੀ ਸੁਵਿਧਾ ਨਹੀਂ ਹੈ।"</string>
<string name="face_error_security_update_required" msgid="5076017208528750161">"ਸੈਂਸਰ ਅਸਥਾਈ ਤੌਰ \'ਤੇ ਬੰਦ ਕੀਤਾ ਗਿਆ।"</string>
<string name="face_name_template" msgid="3877037340223318119">"ਚਿਹਰਾ <xliff:g id="FACEID">%d</xliff:g>"</string>
- <string name="face_app_setting_name" msgid="8130135875458467243">"ਚਿਹਰਾ ਅਣਲਾਕ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string>
- <string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"ਚਿਹਰਾ ਜਾਂ ਸਕ੍ਰੀਨ ਲਾਕ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string>
+ <string name="face_app_setting_name" msgid="8130135875458467243">"ਫ਼ੇਸ ਅਣਲਾਕ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string>
+ <string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"ਫ਼ੇਸ ਜਾਂ ਸਕ੍ਰੀਨ ਲਾਕ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string>
<string name="face_dialog_default_subtitle" msgid="6620492813371195429">"ਜਾਰੀ ਰੱਖਣ ਲਈ ਆਪਣੇ ਚਿਹਰੇ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string>
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"ਜਾਰੀ ਰੱਖਣ ਲਈ ਆਪਣਾ ਚਿਹਰਾ ਜਾਂ ਸਕ੍ਰੀਨ ਲਾਕ ਵਰਤੋ"</string>
<string-array name="face_error_vendor">
@@ -887,7 +887,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"ਸਾਰੀਆਂ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਅਤੇ ਡਾਟੇ ਲਈ ਅਣਲਾਕ ਕਰੋ"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"ਅਧਿਕਤਮ ਚਿਹਰਾ ਅਣਲਾਕ ਕੋਸ਼ਿਸ਼ਾਂ ਵਧੀਆਂ"</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"ਫ਼ੇਸ ਅਣਲਾਕ ਦੀਆਂ ਕੋਸ਼ਿਸ਼ਾਂ ਸੀਮਾ ਤੋਂ ਪਾਰ ਹੋ ਗਈਆਂ"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"ਕੋਈ ਸਿਮ ਕਾਰਡ ਨਹੀਂ"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"ਟੈਬਲੈੱਟ ਵਿੱਚ ਕੋਈ ਸਿਮ ਕਾਰਡ ਨਹੀਂ ਹੈ।"</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"ਤੁਹਾਡੇ Android TV ਡੀਵਾਈਸ ਵਿੱਚ ਕੋਈ ਸਿਮ ਕਾਰਡ ਮੌਜੂਦ ਨਹੀਂ।"</string>
@@ -957,7 +957,7 @@
<string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"ਅਣਲਾਕ ਖੇਤਰ ਦਾ ਵਿਸਤਾਰ ਕਰੋ।"</string>
<string name="keyguard_accessibility_slide_unlock" msgid="2968195219692413046">"ਅਣਲਾਕ ਸਲਾਈਡ ਕਰੋ।"</string>
<string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"ਪੈਟਰਨ ਅਣਲਾਕ।"</string>
- <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"ਚਿਹਰਾ ਅਣਲਾਕ।"</string>
+ <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"ਫ਼ੇਸ ਅਣਲਾਕ।"</string>
<string name="keyguard_accessibility_pin_unlock" msgid="4020864007967340068">"ਪਿੰਨ ਅਣਲਾਕ।"</string>
<string name="keyguard_accessibility_sim_pin_unlock" msgid="4895939120871890557">"ਸਿਮ ਪਿੰਨ ਅਣਲਾਕ।"</string>
<string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"ਸਿਮ Puk ਅਣਲਾਕ।"</string>
@@ -1022,8 +1022,7 @@
<string name="text_copied" msgid="2531420577879738860">"ਟੈਕਸਟ ਕਲਿਪਬੋਰਡ ਤੇ ਕਾਪੀ ਕੀਤਾ।"</string>
<string name="copied" msgid="4675902854553014676">"ਕਾਪੀ ਕੀਤੀ ਗਈ"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> ਤੋਂ ਕਾਪੀ ਕੀਤੇ ਡਾਟੇ ਨੂੰ <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ਵਿੱਚ ਪੇਸਟ ਕੀਤਾ ਗਿਆ"</string>
- <!-- no translation found for pasted_from_clipboard (7355790625710831847) -->
- <skip />
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ਨੇ ਤੁਹਾਡੇ ਕਲਿੱਪਬੋਰਡ ਤੋਂ ਪੇਸਟ ਕੀਤਾ"</string>
<string name="pasted_text" msgid="4298871641549173733">"ਤੁਹਾਡੇ ਵੱਲੋਂ ਕਾਪੀ ਕੀਤੀ ਗਈ ਲਿਖਤ ਨੂੰ <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ਨੇ ਪੇਸਟ ਕੀਤਾ"</string>
<string name="pasted_image" msgid="4729097394781491022">"ਤੁਹਾਡੇ ਵੱਲੋਂ ਕਾਪੀ ਕੀਤੇ ਗਏ ਚਿੱਤਰ ਨੂੰ <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ਨੇ ਪੇਸਟ ਕੀਤਾ"</string>
<string name="pasted_content" msgid="646276353060777131">"ਤੁਹਾਡੇ ਵੱਲੋਂ ਕਾਪੀ ਕੀਤੀ ਗਈ ਸਮੱਗਰੀ ਨੂੰ <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ਨੇ ਪੇਸਟ ਕੀਤਾ"</string>
@@ -1260,14 +1259,10 @@
<string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> ਤਿਆਰ ਕਰ ਰਿਹਾ ਹੈ।"</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"ਐਪਸ ਚਾਲੂ ਕਰ ਰਿਹਾ ਹੈ।"</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"ਬੂਟ ਪੂਰਾ ਕਰ ਰਿਹਾ ਹੈ।"</string>
- <!-- no translation found for fp_enrollment_powerbutton_intent_title (3385634173366119903) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_message (6582149052513682522) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_positive_button (5963520983910436791) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_negative_button (6465764183480190748) -->
- <skip />
+ <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="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>
@@ -1874,10 +1869,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"ਤੁਹਾਡੇ ਪ੍ਰਸ਼ਾਸਕ ਵੱਲੋਂ ਅੱਪਡੇਟ ਕੀਤਾ ਗਿਆ"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"ਤੁਹਾਡੇ ਪ੍ਰਸ਼ਾਸਕ ਵੱਲੋਂ ਮਿਟਾਇਆ ਗਿਆ"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ਠੀਕ ਹੈ"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"ਬੈਟਰੀ ਸੇਵਰ ਗੂੜ੍ਹੇ ਥੀਮ ਨੂੰ ਚਾਲੂ ਕਰਦਾ ਹੈ ਅਤੇ ਬੈਕਗ੍ਰਾਊਂਡ ਸਰਗਰਮੀ, ਕੁਝ ਦ੍ਰਿਸ਼ਟੀਗਤ ਪ੍ਰਭਾਵਾਂ, ਕੁਝ ਖਾਸ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਅਤੇ ਕੁਝ ਨੈੱਟਵਰਕ ਕਨੈਕਸ਼ਨਾਂ ਨੂੰ ਸੀਮਤ ਜਾਂ ਬੰਦ ਕਰਦਾ ਹੈ।\n\n"<annotation id="url">"ਹੋਰ ਜਾਣੋ"</annotation></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>
@@ -1980,10 +1973,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ਐਪ ਫਿਲਹਾਲ ਉਪਲਬਧ ਨਹੀਂ ਹੈ। ਇਸਦਾ ਪ੍ਰਬੰਧਨ <xliff:g id="APP_NAME_1">%2$s</xliff:g> ਵੱਲੋਂ ਕੀਤਾ ਜਾਂਦਾ ਹੈ।"</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"ਹੋਰ ਜਾਣੋ"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"ਐਪ ਤੋਂ ਰੋਕ ਹਟਾਓ"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"ਕੰਮ ਸੰਬੰਧੀ ਐਪਾਂ ਚਾਲੂ ਕਰਨੀਆਂ ਹਨ?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"ਆਪਣੀਆਂ ਕੰਮ ਸੰਬੰਧੀ ਐਪਾਂ ਅਤੇ ਸੂਚਨਾਵਾਂ ਤੱਕ ਪਹੁੰਚ ਪ੍ਰਾਪਤ ਕਰੋ"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"ਚਾਲੂ ਕਰੋ"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"ਐਪ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਐਪ ਇਸ ਵੇਲੇ ਉਪਲਬਧ ਨਹੀਂ ਹੈ।"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index b77be3d..0c143e8 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -649,7 +649,7 @@
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="5085202213036026288">"Nie można zweryfikować twarzy. Sprzęt niedostępny."</string>
- <string name="face_error_timeout" msgid="522924647742024699">"Spróbuj rozpoznania twarzy ponownie."</string>
+ <string name="face_error_timeout" msgid="522924647742024699">"Spróbuj rozpoznawania twarzy ponownie."</string>
<string name="face_error_no_space" msgid="5649264057026021723">"Nie można przechowywać nowych danych twarzy. Usuń stare."</string>
<string name="face_error_canceled" msgid="2164434737103802131">"Analiza twarzy została anulowana."</string>
<string name="face_error_user_canceled" msgid="8553045452825849843">"Użytkownik anulował rozpoznawanie twarzy."</string>
@@ -1915,10 +1915,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Zaktualizowany przez administratora"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Usunięty przez administratora"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"Oszczędzanie baterii uruchamia ciemny motyw oraz wyłącza lub ogranicza aktywność w tle, niektóre efekty wizualne, pewne funkcje oraz wybrane połączenia sieciowe.\n\n"<annotation id="url">"Więcej informacji"</annotation></string>
+ <string name="battery_saver_description" msgid="8518809702138617167">"Oszczędzanie baterii uruchamia ciemny motyw oraz wyłącza lub ogranicza aktywność w tle, niektóre efekty wizualne, pewne funkcje oraz wybrane połączenia sieciowe."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Oszczędzanie danych uniemożliwia niektórym aplikacjom wysyłanie i odbieranie danych w tle, zmniejszając w ten sposób ich użycie. Aplikacja, z której w tej chwili korzystasz, może uzyskiwać dostęp do danych, ale rzadziej. Może to powodować, że obrazy będą się wyświetlać dopiero po kliknięciu."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Włączyć Oszczędzanie danych?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"Włącz"</string>
@@ -2039,10 +2037,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"Aplikacja <xliff:g id="APP_NAME_0">%1$s</xliff:g> nie jest teraz dostępna. Zarządza tym aplikacja <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"Więcej informacji"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Wznów działanie aplikacji"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"Włączyć aplikacje służbowe?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"Uzyskaj dostęp do aplikacji służbowych i powiadomień"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Włącz"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"Aplikacja jest niedostępna"</string>
<string name="app_blocked_message" msgid="542972921087873023">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> jest obecnie niedostępna."</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index bc0342a..8f24a7c 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -887,7 +887,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Tente novamente"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"Tente novamente"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"Desbloqueio para todos os recursos e dados"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"O número máximo de tentativas de Desbloqueio por reconhecimento facial foi excedido"</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"O número máximo de tentativas de desbloqueio por reconhecimento facial foi excedido"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"Sem chip"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"Não há um chip no tablet."</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"Nenhum chip no seu dispositivo Android TV."</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index db561c9..3e29cb0 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1869,10 +1869,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Atualizado pelo seu gestor"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Eliminado pelo seu gestor"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"A Poupança de bateria ativa o tema escuro e limita ou desativa a atividade em segundo plano, alguns efeitos visuais, determinadas funcionalidades e algumas ligações de rede.\n\n"<annotation id="url">"Saiba mais"</annotation></string>
+ <string name="battery_saver_description" msgid="8518809702138617167">"A Poupança de bateria ativa o tema escuro e limita ou desativa a atividade em segundo plano, alguns efeitos visuais, determinadas funcionalidades e algumas ligações de rede."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Para ajudar a reduzir a utilização de dados, a Poupança de dados impede que algumas aplicações enviem ou recebam dados em segundo plano. Uma determinada app que esteja a utilizar atualmente pode aceder aos dados, mas é possível que o faça com menos frequência. Isto pode significar, por exemplo, que as imagens não são apresentadas até que toque nas mesmas."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Pretende ativar a Poupança de dados?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"Ativar"</string>
@@ -1975,10 +1973,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"A app <xliff:g id="APP_NAME_0">%1$s</xliff:g> não está disponível neste momento. A app <xliff:g id="APP_NAME_1">%2$s</xliff:g> gere esta definição."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"Saiba mais"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Retomar app"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"Ativar as apps de trabalho?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"Obtenha acesso às suas apps de trabalho e notificações"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Ativar"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"A app não está disponível"</string>
<string name="app_blocked_message" msgid="542972921087873023">"De momento, a app <xliff:g id="APP_NAME">%1$s</xliff:g> não está disponível."</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index bc0342a..8f24a7c 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -887,7 +887,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Tente novamente"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"Tente novamente"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"Desbloqueio para todos os recursos e dados"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"O número máximo de tentativas de Desbloqueio por reconhecimento facial foi excedido"</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"O número máximo de tentativas de desbloqueio por reconhecimento facial foi excedido"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"Sem chip"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"Não há um chip no tablet."</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"Nenhum chip no seu dispositivo Android TV."</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 022e1ca..a202de6 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -658,7 +658,7 @@
<string name="face_error_security_update_required" msgid="5076017208528750161">"Senzorul este dezactivat temporar."</string>
<string name="face_name_template" msgid="3877037340223318119">"Chip <xliff:g id="FACEID">%d</xliff:g>"</string>
<string name="face_app_setting_name" msgid="8130135875458467243">"Folosiți deblocarea facială"</string>
- <string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"Folosiți blocarea ecranului sau blocarea facială"</string>
+ <string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"Folosiți deblocarea facială sau ecranul de blocare"</string>
<string name="face_dialog_default_subtitle" msgid="6620492813371195429">"Folosiți-vă chipul ca să continuați"</string>
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Folosiți-vă chipul sau blocarea ecranului pentru a continua"</string>
<string-array name="face_error_vendor">
@@ -1025,8 +1025,7 @@
<string name="text_copied" msgid="2531420577879738860">"Text copiat în clipboard."</string>
<string name="copied" msgid="4675902854553014676">"Copiat"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> a inserat date din <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>"</string>
- <!-- no translation found for pasted_from_clipboard (7355790625710831847) -->
- <skip />
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> a inserat din clipboard"</string>
<string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> a inserat textul copiat"</string>
<string name="pasted_image" msgid="4729097394781491022">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> a inserat o imagine copiată"</string>
<string name="pasted_content" msgid="646276353060777131">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> a inserat conținutul copiat"</string>
@@ -1280,14 +1279,10 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Se pregătește <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Se pornesc aplicațiile."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Se finalizează pornirea."</string>
- <!-- no translation found for fp_enrollment_powerbutton_intent_title (3385634173366119903) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_message (6582149052513682522) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_positive_button (5963520983910436791) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_negative_button (6465764183480190748) -->
- <skip />
+ <string name="fp_enrollment_powerbutton_intent_title" msgid="3385634173366119903">"Dezactivați ecranul?"</string>
+ <string name="fp_enrollment_powerbutton_intent_message" msgid="6582149052513682522">"Ați apăsat butonul de pornire în timpul configurării amprentei.\n\nDe obicei, această acțiune dezactivează ecranul."</string>
+ <string name="fp_enrollment_powerbutton_intent_positive_button" msgid="5963520983910436791">"Dezactivați"</string>
+ <string name="fp_enrollment_powerbutton_intent_negative_button" msgid="6465764183480190748">"Anulați"</string>
<string name="heavy_weight_notification" msgid="8382784283600329576">"Rulează <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="heavy_weight_notification_detail" msgid="6802247239468404078">"Atingeți pentru a reveni la joc"</string>
<string name="heavy_weight_switcher_title" msgid="3861984210040100886">"Alegeți jocul"</string>
@@ -1740,8 +1735,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Utilizați comanda rapidă"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Inversarea culorilor"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Corecția culorii"</string>
- <!-- no translation found for one_handed_mode_feature_name (2334330034828094891) -->
- <skip />
+ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Modul cu o mână"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Luminozitate redusă suplimentar"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"S-au apăsat lung tastele de volum. S-a activat <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"S-au apăsat lung tastele de volum. S-a dezactivat <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
@@ -1898,10 +1892,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Actualizat de administratorul dvs."</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Șters de administratorul dvs."</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"Economisirea bateriei activează tema întunecată și restricționează sau dezactivează activitatea în fundal, unele efecte vizuale, alte funcții și câteva conexiuni de rețea.\n\n"<annotation id="url">"Aflați mai multe"</annotation></string>
+ <string name="battery_saver_description" msgid="8518809702138617167">"Economisirea bateriei activează tema întunecată și restricționează sau dezactivează activitatea în fundal, unele efecte vizuale, alte funcții și câteva conexiuni la rețea."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Pentru a contribui la reducerea utilizării de date, Economizorul de date împiedică unele aplicații să trimită sau să primească date în fundal. O aplicație pe care o folosiți poate accesa datele, însă mai rar. Aceasta poate însemna, de exemplu, că imaginile se afișează numai după ce le atingeți."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Activați Economizorul de date?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"Activați"</string>
@@ -2013,10 +2005,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"Momentan, aplicația <xliff:g id="APP_NAME_0">%1$s</xliff:g> nu este disponibilă. Aceasta este gestionată de <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"Aflați mai multe"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Anulați întreruperea aplicației"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"Activați aplicațiile pentru lucru?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"Obțineți acces la aplicațiile pentru lucru și notificări"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Activați"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"Aplicația nu este disponibilă"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> nu este disponibilă momentan."</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 86a0c0d..9fe0f7e 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -618,7 +618,7 @@
<string name="permlab_manageFace" msgid="4569549381889283282">"Управление аппаратным обеспечением для функции \"Фейсконтроль\""</string>
<string name="permdesc_manageFace" msgid="6204569688492710471">"Приложение сможет добавлять и удалять шаблоны лиц."</string>
<string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"Использование аппаратного обеспечения для функции \"Фейсконтроль\""</string>
- <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Приложение сможет использовать для аутентификации аппаратное обеспечение Фейсконтроля."</string>
+ <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Приложение сможет использовать для аутентификации аппаратное обеспечение фейсконтроля."</string>
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Фейсконтроль"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Зарегистрируйте лицо ещё раз"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Чтобы улучшить распознавание лица, зарегистрируйте его ещё раз"</string>
@@ -649,7 +649,7 @@
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="5085202213036026288">"Не удалось распознать лицо. Сканер недоступен."</string>
- <string name="face_error_timeout" msgid="522924647742024699">"Попробуйте воспользоваться функцией ещё раз."</string>
+ <string name="face_error_timeout" msgid="522924647742024699">"Попробуйте воспользоваться фейсконтролем ещё раз."</string>
<string name="face_error_no_space" msgid="5649264057026021723">"Недостаточно места. Удалите старые данные для распознавания."</string>
<string name="face_error_canceled" msgid="2164434737103802131">"Распознавание отменено"</string>
<string name="face_error_user_canceled" msgid="8553045452825849843">"Фейсконтроль: операция отменена пользователем."</string>
@@ -893,7 +893,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Повторите попытку"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"Повторите попытку"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"Разблок. для доступа ко всем функциям и данным"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Все попытки войти с помощью Фейсконтроля использованы"</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Все попытки войти с помощью фейсконтроля использованы"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"Нет SIM-карты"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"SIM-карта не установлена."</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"В устройстве Android TV нет SIM-карты."</string>
@@ -1028,8 +1028,7 @@
<string name="text_copied" msgid="2531420577879738860">"Текст скопирован в буфер обмена."</string>
<string name="copied" msgid="4675902854553014676">"Скопировано"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"Данные из приложения \"<xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>\" вставлены в приложение \"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>\"."</string>
- <!-- no translation found for pasted_from_clipboard (7355790625710831847) -->
- <skip />
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"Приложение \"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>\" вставило данные из буфера обмена."</string>
<string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>: скопированный текст вставлен"</string>
<string name="pasted_image" msgid="4729097394781491022">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>: скопированное изображение вставлено"</string>
<string name="pasted_content" msgid="646276353060777131">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>: скопированный контент вставлен"</string>
@@ -1300,14 +1299,10 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Подготовка приложения \"<xliff:g id="APPNAME">%1$s</xliff:g>\"..."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Запуск приложений."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Окончание загрузки..."</string>
- <!-- no translation found for fp_enrollment_powerbutton_intent_title (3385634173366119903) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_message (6582149052513682522) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_positive_button (5963520983910436791) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_negative_button (6465764183480190748) -->
- <skip />
+ <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="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>
@@ -1762,8 +1757,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Использовать быстрое включение"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Инверсия цветов"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Коррекция цвета"</string>
- <!-- no translation found for one_handed_mode_feature_name (2334330034828094891) -->
- <skip />
+ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Режим управления одной рукой"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Дополнительное уменьшение яркости"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Использован жест с кнопками регулировки громкости. Функция \"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\" включена."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Использован жест с кнопками регулировки громкости. Функция \"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\" отключена."</string>
@@ -1921,10 +1915,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Обновлено администратором"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Удалено администратором"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ОК"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"В режиме энергосбережения включается тёмная тема, ограничиваются или отключаются фоновые процессы, некоторые визуальные эффекты, определенные функции и ряд сетевых подключений.\n\n"<annotation id="url">"Подробнее…"</annotation></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>
@@ -2045,10 +2037,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"Приложение \"<xliff:g id="APP_NAME_0">%1$s</xliff:g>\" недоступно. Его работу ограничивает приложение \"<xliff:g id="APP_NAME_1">%2$s</xliff:g>\"."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"Подробнее"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Возобновить работу приложения"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"Включить рабочие приложения?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"Вы получите доступ к рабочим приложениям и уведомлениям"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Включить"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"Приложение недоступно"</string>
<string name="app_blocked_message" msgid="542972921087873023">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" сейчас недоступно."</string>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index 5d38e46..e5e0367 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -609,14 +609,14 @@
<string-array name="fingerprint_error_vendor">
</string-array>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"ඇඟිලි සලකුණු නිරූපකය"</string>
- <string name="permlab_manageFace" msgid="4569549381889283282">"මුහුණු අඟුලු ඇරීමේ දෘඪාංග කළමනා කරන්න"</string>
+ <string name="permlab_manageFace" msgid="4569549381889283282">"මුහුණෙන් අගුළු හැරීම දෘඪාංග කළමනා කරන්න"</string>
<string name="permdesc_manageFace" msgid="6204569688492710471">"මුහුණු අච්චු එකතු කිරීමට සහ ඉවත් කිරීමට අදාළ ක්රම භාවිතය සඳහා මෙම යෙදුමට ඉඩ දෙයි."</string>
- <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"මුහුණු අඟුලු ඇරීමේ දෘඪාංග භෘවිත කරන්න"</string>
- <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"සත්යාපනය සඳහා මුහුණු අඟුලු ඇරීමේ දෘඪාංග භාවිත කිරීමට යෙදුමට ඉඩ දෙයි"</string>
- <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"මුහුණු අඟුලු ඇරීම"</string>
+ <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"මුහුණෙන් අගුළු හැරීමේ දෘඪාංග භෘවිත කරන්න"</string>
+ <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"සත්යාපනය සඳහා මුහුණෙන් අගුළු හැරීමේ දෘඪාංග භාවිත කිරීමට යෙදුමට ඉඩ දෙයි"</string>
+ <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"මුහුණෙන් අගුළු හැරීම"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"ඔබේ මුහුණ යළි ලියාපදිංචි කරන්න"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"හඳුනා ගැනීම වැඩිදියුණු කිරීමට, ඔබේ මුහුණ යළි-ලියාපදිංචි කරන්න"</string>
- <string name="face_setup_notification_title" msgid="550617822603450009">"මුහුණු අඟුලු හැරීම පිහිටුවන්න"</string>
+ <string name="face_setup_notification_title" msgid="550617822603450009">"මුහුණෙන් අගුළු හැරීම පිහිටුවන්න"</string>
<string name="face_setup_notification_content" msgid="5463999831057751676">"ඔබගේ දුරකථනය දෙස බැලීමෙන් එහි අගුලු හරින්න"</string>
<string name="fingerprint_setup_notification_title" msgid="2002630611398849495">"අගුලු හැරීමට තවත් ක්රම සකසන්න"</string>
<string name="fingerprint_setup_notification_content" msgid="205578121848324852">"ඇඟිලි සලකුණක් එක් කිරීමට තට්ටු කරන්න"</string>
@@ -643,19 +643,19 @@
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="5085202213036026288">"මුහුණ සත්යාපනය කළ නොහැක. දෘඩාංගය නොමැත."</string>
- <string name="face_error_timeout" msgid="522924647742024699">"නැවතත් මුහුණු අඟුලු ඇරීම උත්සාහ කරන්න."</string>
+ <string name="face_error_timeout" msgid="522924647742024699">"නැවතත් මුහුණෙන් අගුළු හැරීම උත්සාහ කරන්න."</string>
<string name="face_error_no_space" msgid="5649264057026021723">"නව මුහුණු දත්ත ගබඩා කළ නොහැක. පළමුව පැරණි එකක් මකන්න."</string>
<string name="face_error_canceled" msgid="2164434737103802131">"මුහුණු මෙහෙයුම අවලංගු කරන ලදී."</string>
- <string name="face_error_user_canceled" msgid="8553045452825849843">"පරිශීලකයා මුහුණු අඟුලු ඇරීම අවලංගු කර ඇත."</string>
+ <string name="face_error_user_canceled" msgid="8553045452825849843">"පරිශීලකයා මුහුණෙන් අගුළු හැරීම අවලංගු කර ඇත."</string>
<string name="face_error_lockout" msgid="7864408714994529437">"උත්සාහයන් ඉතා වැඩි ගණනකි. පසුව නැවත උත්සාහ කරන්න."</string>
- <string name="face_error_lockout_permanent" msgid="8277853602168960343">"ප්රයත්න ගණන වැඩියි. මුහුණු අඟුලු ඇරීම අබලයි."</string>
+ <string name="face_error_lockout_permanent" msgid="8277853602168960343">"ප්රයත්න ගණන වැඩියි. මුහුණෙන් අගුළු හැරීම අබලයි."</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"මුහුණ සත්යාපන කළ නොහැක. නැවත උත්සාහ කරන්න."</string>
- <string name="face_error_not_enrolled" msgid="7369928733504691611">"ඔබ මුහුණු අඟුලු ඇරීම සකසා නැත"</string>
- <string name="face_error_hw_not_present" msgid="1070600921591729944">"මෙම උපාංගයෙහි මුහුණු අඟුලු ඇරීමට සහය නොදැක්වේ"</string>
+ <string name="face_error_not_enrolled" msgid="7369928733504691611">"ඔබ මුහුණෙන් අගුළු හැරීම සකසා නැත"</string>
+ <string name="face_error_hw_not_present" msgid="1070600921591729944">"මෙම උපාංගයෙහි මුහුණෙන් අගුළු හැරීම සහය නොදැක්වේ"</string>
<string name="face_error_security_update_required" msgid="5076017208528750161">"සංවේදකය තාවකාලිකව අබල කර ඇත."</string>
<string name="face_name_template" msgid="3877037340223318119">"මුහුණු <xliff:g id="FACEID">%d</xliff:g>"</string>
- <string name="face_app_setting_name" msgid="8130135875458467243">"මුහුණු අගුලු හැරීම භාවිත කරන්න"</string>
- <string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"මුහුණු අගුලු හැරීම හෝ තිර අගුල භාවිත කරන්න"</string>
+ <string name="face_app_setting_name" msgid="8130135875458467243">"මුහුණෙන් අගුළු හැරීම භාවිත කරන්න"</string>
+ <string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"මුහුණෙන් අගුළු හැරීම හෝ තිර අගුල භාවිත කරන්න"</string>
<string name="face_dialog_default_subtitle" msgid="6620492813371195429">"ඉදිරියට යාමට ඔබගේ මුහුණ භාවිත කරන්න"</string>
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"ඉදිරියට යාමට ඔබගේ මුහුණු හෝ තිර අගුල භාවිත කරන්න"</string>
<string-array name="face_error_vendor">
@@ -887,7 +887,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"නැවත උත්සාහ කරන්න"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"නැවත උත්සාහ කරන්න"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"සියලු විශේෂාංග සහ දත්ත අනවහිර කරන්න"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"මුහුණ භාවිතයෙන් අඟුළු හැරීමේ උපරිම ප්රයන්තයන් ගණන ඉක්මවා ඇත"</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"මුහුණෙන් අගුළු හැරීමේ උපරිම ප්රයන්තයන් ගණන ඉක්මවා ඇත"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"SIM පත නැත"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"ටැබ්ලටයේ SIM පත නොමැත."</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"ඔබගේ Android TV උපාංගයේ SIM කාඩ්පතක් නොමැත."</string>
@@ -957,7 +957,7 @@
<string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"අගුළු නොදැමූ ප්රදේශය පුළුල් කරන්න."</string>
<string name="keyguard_accessibility_slide_unlock" msgid="2968195219692413046">"සර්පණ අගුළු ඇරීම."</string>
<string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"රටා අගුළු ඇරීම."</string>
- <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"මුහුණ භාවිතයෙන් අඟුළු හැරීම."</string>
+ <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"මුහුණෙන් අගුළු හැරීම."</string>
<string name="keyguard_accessibility_pin_unlock" msgid="4020864007967340068">"PIN අගුළු ඇරීම."</string>
<string name="keyguard_accessibility_sim_pin_unlock" msgid="4895939120871890557">"Sim Pin අගුලු දැමීම."</string>
<string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"Sim Puk අගුලු දැමීම."</string>
@@ -1713,8 +1713,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"කෙටිමඟ භාවිතා කරන්න"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"වර්ණ අපවර්තනය"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"වර්ණ නිවැරදි කිරීම"</string>
- <!-- no translation found for one_handed_mode_feature_name (2334330034828094891) -->
- <skip />
+ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"තනි අත් ප්රකාරය"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"තවත් අඳුරු"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"හඬ පරිමා යතුරු අල්ලා ගන්න <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ක්රියාත්මකයි."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"හඬ පරිමා යතුරු අල්ලා ගන්න <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ක්රියාවිරහිතයි."</string>
@@ -1870,10 +1869,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"ඔබගේ පරිපාලක මඟින් යාවත්කාලීන කර ඇත"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"ඔබගේ පරිපාලක මඟින් මකා දමා ඇත"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"හරි"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"බැටරි සුරැකුම අඳුරු තේමාව ක්රියාත්මක කර පසුබිම් ක්රියාකාරකම්, සමහර දෘශ්ය ප්රයෝග, යම් විශේෂාංග සහ සමහර ජාල සම්බන්ධතා සීමා හෝ ක්රියාවිරහිත කරයි.\n\n"<annotation id="url">"තව දැන ගන්න"</annotation></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>
@@ -1976,10 +1973,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> මේ අවස්ථාවේදී ලබා ගත නොහැකිය. මෙය <xliff:g id="APP_NAME_1">%2$s</xliff:g> මගින් කළමනාකරණය කෙරේ."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"තව දැන ගන්න"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"යෙදුම විරාම කිරීම ඉවත් කරන්න"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"කාර්යාල යෙදු. ක්රියා. කරන්නද?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"ඔබගේ කාර්යාල යෙදුම් සහ දැනුම්දීම් වෙත ප්රවේශය ලබා ගන්න"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"ක්රියාත්මක කරන්න"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"යෙදුම ලබා ගත නොහැකිය"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> මේ දැන් ලබා ගත නොහැකිය."</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index ac5483a..556b590 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -617,8 +617,8 @@
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikona odtlačku prsta"</string>
<string name="permlab_manageFace" msgid="4569549381889283282">"spravovať hardvér odomknutia tvárou"</string>
<string name="permdesc_manageFace" msgid="6204569688492710471">"Umožňuje aplikácii vyvolať metódy, ktoré pridávajú a odstraňujú šablóny tvárí."</string>
- <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"používať hardvér Odomknutia tvárou"</string>
- <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Umožňuje aplikácii používať na overenie totožnosti hardvér Odomknutia tvárou"</string>
+ <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"používať hardvér odomknutia tvárou"</string>
+ <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Umožňuje aplikácii používať na overenie totožnosti hardvér odomknutia tvárou"</string>
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Odomknutie tvárou"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Znova zaregistrujte svoju tvár"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Znova zaregistrujte svoju tvár, aby sa zlepšilo rozpoznávanie"</string>
@@ -1757,8 +1757,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Použiť skratku"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Inverzia farieb"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Úprava farieb"</string>
- <!-- no translation found for one_handed_mode_feature_name (2334330034828094891) -->
- <skip />
+ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Režim jednej ruky"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Veľmi tmavé"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Pridržali ste tlačidlá hlasitosti. Služba <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je zapnutá."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Pridržali ste tlačidlá hlasitosti. Služba <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je vypnutá."</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 7dce148..b18afc3 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -1028,8 +1028,7 @@
<string name="text_copied" msgid="2531420577879738860">"Besedilo, kopirano v odložišče."</string>
<string name="copied" msgid="4675902854553014676">"Kopirano"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"Aplikacija <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> je prilepila iz aplikacije <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>."</string>
- <!-- no translation found for pasted_from_clipboard (7355790625710831847) -->
- <skip />
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"Aplikacija <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> je prilepila iz odložišča."</string>
<string name="pasted_text" msgid="4298871641549173733">"Aplikacija <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> je prilepila besedilo iz odložišča."</string>
<string name="pasted_image" msgid="4729097394781491022">"Aplikacija <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> je prilepila sliko iz odložišča."</string>
<string name="pasted_content" msgid="646276353060777131">"Aplikacija <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> je prilepila vsebino iz odložišča."</string>
@@ -1300,14 +1299,10 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Pripravljanje aplikacije <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Zagon aplikacij."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Dokončevanje zagona."</string>
- <!-- no translation found for fp_enrollment_powerbutton_intent_title (3385634173366119903) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_message (6582149052513682522) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_positive_button (5963520983910436791) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_negative_button (6465764183480190748) -->
- <skip />
+ <string name="fp_enrollment_powerbutton_intent_title" msgid="3385634173366119903">"Želite izklopiti zaslon?"</string>
+ <string name="fp_enrollment_powerbutton_intent_message" msgid="6582149052513682522">"Pri nastavljanju prstnega odtisa ste pritisnili gumb za vklop.\n\nS tem običajno izklopite zaslon."</string>
+ <string name="fp_enrollment_powerbutton_intent_positive_button" msgid="5963520983910436791">"Izklopi"</string>
+ <string name="fp_enrollment_powerbutton_intent_negative_button" msgid="6465764183480190748">"Prekliči"</string>
<string name="heavy_weight_notification" msgid="8382784283600329576">"<xliff:g id="APP">%1$s</xliff:g> se izvaja"</string>
<string name="heavy_weight_notification_detail" msgid="6802247239468404078">"Dotaknite se za vrnitev v igro"</string>
<string name="heavy_weight_switcher_title" msgid="3861984210040100886">"Izberite igro"</string>
@@ -1762,8 +1757,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Uporabi bližnjico"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Inverzija barv"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Popravljanje barv"</string>
- <!-- no translation found for one_handed_mode_feature_name (2334330034828094891) -->
- <skip />
+ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Enoročni način"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Zelo zatemnjeno"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Tipki za glasnost sta pridržani. Storitev <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je vklopljena."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Tipki za glasnost sta pridržani. Storitev <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je izklopljena."</string>
@@ -1921,10 +1915,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Posodobil skrbnik"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Izbrisal skrbnik"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"V redu"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"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.\n\n"<annotation id="url">"Več o tem"</annotation></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_enable_title" msgid="7080620065745260137">"Vklop varčevanja s podatki?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"Vklopi"</string>
@@ -2045,10 +2037,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"Aplikacija <xliff:g id="APP_NAME_0">%1$s</xliff:g> trenutno ni na voljo. To upravlja aplikacija <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"Več o tem"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Prekliči začasno zaustavitev aplikacije"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"Vklop delovnih aplikacij?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"Omogočanje dostopa do delovnih aplikacij in obvestil za delovni profil"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Vklop"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"Aplikacija ni na voljo"</string>
<string name="app_blocked_message" msgid="542972921087873023">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> trenutno ni na voljo."</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index d895f74..911dbc1 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -609,10 +609,10 @@
<string-array name="fingerprint_error_vendor">
</string-array>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikona e gjurmës së gishtit"</string>
- <string name="permlab_manageFace" msgid="4569549381889283282">"menaxho harduerin për shkyçjen me fytyrën"</string>
+ <string name="permlab_manageFace" msgid="4569549381889283282">"menaxho harduerin për shkyçjen me fytyrë"</string>
<string name="permdesc_manageFace" msgid="6204569688492710471">"Lejon aplikacionin të aktivizojë mënyra për shtim e fshirje të shablloneve të përdorura."</string>
- <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"përdor harduerin e shkyçjes me fytyrën"</string>
- <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Lejon aplikacionin të përdorë harduerin e shkyçjes me fytyrën për procesin e vërtetimit"</string>
+ <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"përdor harduerin e shkyçjes me fytyrë"</string>
+ <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Lejon aplikacionin të përdorë harduerin e shkyçjes me fytyrë për procesin e vërtetimit"</string>
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Shkyçja me fytyrë"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Regjistro përsëri fytyrën tënde"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Për të përmirësuar njohjen, regjistro përsëri fytyrën tënde"</string>
@@ -643,7 +643,7 @@
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="5085202213036026288">"Fytyra s\'mund të verifikohet. Hardueri nuk ofrohet."</string>
- <string name="face_error_timeout" msgid="522924647742024699">"Provo përsëri shkyçjen me fytyrën."</string>
+ <string name="face_error_timeout" msgid="522924647742024699">"Provo përsëri shkyçjen me fytyrë."</string>
<string name="face_error_no_space" msgid="5649264057026021723">"S\'mund të ruhen të dhëna të reja fytyre. Fshi një të vjetër në fillim."</string>
<string name="face_error_canceled" msgid="2164434737103802131">"Veprimi me fytyrën u anulua."</string>
<string name="face_error_user_canceled" msgid="8553045452825849843">"Shkyçja me fytyrë u anulua nga përdoruesi."</string>
@@ -887,7 +887,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Provo sërish"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"Provo sërish"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"Shkyçe për të gjitha funksionet dhe të dhënat"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Tentativat maksimale të \"Shkyçjes me fytyrë\" u tejkaluan"</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Përpjektet maksimale të \"Shkyçjes me fytyrë\" u tejkaluan"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"Nuk ka kartë SIM"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"Nuk ka kartë SIM në tablet."</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"Nuk ka kartë SIM në pajisjen tënde Android TV."</string>
@@ -957,7 +957,7 @@
<string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"Zgjero zonën e shkyçjes."</string>
<string name="keyguard_accessibility_slide_unlock" msgid="2968195219692413046">"Rrëshqit shkyçjen."</string>
<string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"Shkyçje me motiv."</string>
- <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"Shkyçje me fytyrë."</string>
+ <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"Shkyçja me fytyrë."</string>
<string name="keyguard_accessibility_pin_unlock" msgid="4020864007967340068">"Shkyçje me PIN."</string>
<string name="keyguard_accessibility_sim_pin_unlock" msgid="4895939120871890557">"Shkyçja e kartës SIM me kodin PIN"</string>
<string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"Shkyçja e kartës SIM me kodin PUK"</string>
@@ -1713,8 +1713,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Përdor shkurtoren"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Anasjellja e ngjyrës"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Korrigjimi i ngjyrës"</string>
- <!-- no translation found for one_handed_mode_feature_name (2334330034828094891) -->
- <skip />
+ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Modaliteti i përdorimit me një dorë"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Shumë më i zbehtë"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Tastet e volumit të mbajtura shtypur. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> i aktivizuar."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Tastet e volumit të mbajtura shtypur. U çaktivizua \"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\"."</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 3512945..44644fd 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -1892,10 +1892,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Ажурирао је администратор"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Избрисао је администратор"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"Потврди"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"Уштеда батерије укључује Тамну тему и ограничава или искључује активности у позадини, неке визуелне ефекте, одређене функције и мрежне везе.\n\n"<annotation id="url">"Сазнајте више"</annotation></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>
@@ -2007,10 +2005,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"Апликација <xliff:g id="APP_NAME_0">%1$s</xliff:g> тренутно није доступна. <xliff:g id="APP_NAME_1">%2$s</xliff:g> управља доступношћу."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"Сазнајте више"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Опозови паузирање апликације"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"Укључити пословне апликације?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"Приступајте пословним апликацијама и обавештењима"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Укључи"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"Апликација није доступна"</string>
<string name="app_blocked_message" msgid="542972921087873023">"Апликација <xliff:g id="APP_NAME">%1$s</xliff:g> тренутно није доступна."</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 71fcb7d..c6df5f9 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -887,7 +887,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Försök igen"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"Försök igen"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"Lås upp för alla funktioner och all data"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Du har försökt låsa upp med Ansiktslås för många gånger"</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Du har försökt låsa upp med ansiktslås för många gånger"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"Inget SIM-kort"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"Inget SIM-kort i surfplattan."</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"Inget SIM-kort i Android TV-enheten."</string>
@@ -1713,8 +1713,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Använd kortkommandot"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Inverterade färger"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Färgkorrigering"</string>
- <!-- no translation found for one_handed_mode_feature_name (2334330034828094891) -->
- <skip />
+ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Enhandsläge"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Extradimmat"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Volymknapparna har tryckts ned. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> har aktiverats."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Volymknapparna har tryckts ned. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> har inaktiverats."</string>
@@ -1870,10 +1869,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Administratören uppdaterade paketet"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Administratören raderade paketet"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"I batterisparläget aktiveras mörkt tema medan bakgrundsaktivitet, vissa visuella effekter och funktioner samt vissa nätverksanslutningar begränsas eller inaktiveras.\n\n"<annotation id="url">"Läs mer"</annotation></string>
+ <string name="battery_saver_description" msgid="8518809702138617167">"I batterisparläget aktiveras mörkt tema medan bakgrundsaktivitet, vissa visuella effekter och funktioner samt vissa nätverksanslutningar begränsas eller inaktiveras."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Med Databesparing kan du minska dataanvändningen genom att hindra en del appar från att skicka eller ta emot data i bakgrunden. Appar som du använder kan komma åt data, men det sker kanske inte lika ofta. Detta innebär t.ex. att bilder inte visas förrän du trycker på dem."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Vill du aktivera Databesparing?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"Aktivera"</string>
@@ -1976,10 +1973,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> är inte tillgänglig just nu. Detta hanteras av <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"Läs mer"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Återuppta app"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"Vill du aktivera jobbappar?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"Få åtkomst till jobbappar och aviseringar"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Aktivera"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"Appen är inte tillgänglig"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> är inte tillgängligt just nu."</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index cf22492..baca154 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -887,7 +887,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Jaribu tena"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"Jaribu tena"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"Fungua kifaa ili upate data na vipengele vyote"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Umepitisha idadi ya juu ya mara ambazo unaweza kujaribu Kufungua kwa Uso"</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Umepitisha idadi ya juu ya mara ambazo unaweza kujaribu kufungua kwa uso"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"Hakuna SIM kadi"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"Hakuna SIM kadi katika kompyuta ndogo."</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"Hakuna SIM kadi kwenye kifaa chako cha Android TV."</string>
@@ -1022,8 +1022,7 @@
<string name="text_copied" msgid="2531420577879738860">"Maandishi yamenakiliwa kwenye ubao wa kunakili."</string>
<string name="copied" msgid="4675902854553014676">"Umenakili"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> imebandika kutoka <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>"</string>
- <!-- no translation found for pasted_from_clipboard (7355790625710831847) -->
- <skip />
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> imebandika kutoka ubao wako wa kunakili"</string>
<string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> imebandika maandishi uliyonakili"</string>
<string name="pasted_image" msgid="4729097394781491022">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> imebandika picha uliyonakili"</string>
<string name="pasted_content" msgid="646276353060777131">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> imebandika maudhui uliyonakili"</string>
@@ -1260,14 +1259,10 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Inaandaa <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Programu zinaanza"</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Inamaliza kuwasha."</string>
- <!-- no translation found for fp_enrollment_powerbutton_intent_title (3385634173366119903) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_message (6582149052513682522) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_positive_button (5963520983910436791) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_negative_button (6465764183480190748) -->
- <skip />
+ <string name="fp_enrollment_powerbutton_intent_title" msgid="3385634173366119903">"Ungependa kuzima skrini?"</string>
+ <string name="fp_enrollment_powerbutton_intent_message" msgid="6582149052513682522">"Ulipokuwa ukiweka alama ya kidole chako, ulibonyeza Kitufe cha kuwasha/kuzima.\n\nKwa kawaida, hatua hii huzima skrini yako."</string>
+ <string name="fp_enrollment_powerbutton_intent_positive_button" msgid="5963520983910436791">"Zima"</string>
+ <string name="fp_enrollment_powerbutton_intent_negative_button" msgid="6465764183480190748">"Ghairi"</string>
<string name="heavy_weight_notification" msgid="8382784283600329576">"<xliff:g id="APP">%1$s</xliff:g> inaendelea"</string>
<string name="heavy_weight_notification_detail" msgid="6802247239468404078">"Gusa ili urudi kwenye mchezo"</string>
<string name="heavy_weight_switcher_title" msgid="3861984210040100886">"Chagua mchezo"</string>
@@ -1718,8 +1713,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Tumia Njia ya Mkato"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Ugeuzaji rangi"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Usahihishaji wa rangi"</string>
- <!-- no translation found for one_handed_mode_feature_name (2334330034828094891) -->
- <skip />
+ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Hali ya kutumia kwa mkono mmoja"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Kipunguza mwangaza zaidi"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Vitufe vya sauti vilivyoshikiliwa. Umewasha <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Vitufe vya sauti vimeshikiliwa. Umezima <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
@@ -1875,10 +1869,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Imesasishwa na msimamizi wako"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Imefutwa na msimamizi wako"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"Sawa"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"Kiokoa Betri huwasha Mandhari meusi na kudhibiti au kuzima shughuli za chinichini, baadhi ya madoido yanayoonekana, vipengele fulani na baadhi ya miunganisho ya mtandao.\n\n"<annotation id="url">"Pata maelezo zaidi"</annotation></string>
+ <string name="battery_saver_description" msgid="8518809702138617167">"Kiokoa Betri huwasha Mandhari meusi na kudhibiti au kuzima shughuli za chinichini, baadhi ya madoido yanayoonekana, vipengele fulani na baadhi ya miunganisho ya mtandao."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Ili kusaidia kupunguza matumizi ya data, Kiokoa Data huzuia baadhi ya programu kupokea na kutuma data chinichini. Programu ambayo unatumia sasa inaweza kufikia data, lakini si kila wakati. Kwa mfano, haitaonyesha picha hadi utakapozifungua."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Ungependa Kuwasha Kiokoa Data?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"Washa"</string>
@@ -1981,10 +1973,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> haipatikani kwa sasa. Inasimamiwa na <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"Pata maelezo zaidi"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Acha kusimamisha programu"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"Utawasha programu za kazini?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"Pata uwezo wa kufikia arifa na programu zako za kazini"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Washa"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"Programu haipatikani"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> haipatikani hivi sasa."</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index 7d853ee..1f43483 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -609,14 +609,14 @@
<string-array name="fingerprint_error_vendor">
</string-array>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"கைரேகை ஐகான்"</string>
- <string name="permlab_manageFace" msgid="4569549381889283282">"\'முகம் காட்டித் திறத்தலுக்கான\' வன்பொருளை நிர்வகித்தல்"</string>
+ <string name="permlab_manageFace" msgid="4569549381889283282">"\'முகம் காட்டித் திறத்தல்\' அம்சத்துக்கான வன்பொருளை நிர்வகித்தல்"</string>
<string name="permdesc_manageFace" msgid="6204569688492710471">"உபயோகிப்பதற்காக முக டெம்ப்ளேட்டுகளை சேர்க்கும்/நீக்கும் முறைகளை இயக்க, ஆப்ஸை அனுமதிக்கும்."</string>
<string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"’முகம் காட்டித் திறத்தல்’ அம்சத்திற்கான வன்பொருளைப் பயன்படுத்துதல்"</string>
<string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"அடையாளம் காண \'முகம் காட்டித் திறத்தலுக்கான\' வன்பொருளைப் பயன்படுத்த ஆப்ஸை அனுமதிக்கும்"</string>
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"முகம் காட்டித் திறத்தல்"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"முகத்தை மீண்டும் பதிவுசெய்யவும்"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"அடையாளத்தை மேம்படுத்த முகத்தை மீண்டும் பதிவுசெய்யவும்"</string>
- <string name="face_setup_notification_title" msgid="550617822603450009">"முகம் காட்டித் திறத்தலை அமையுங்கள்"</string>
+ <string name="face_setup_notification_title" msgid="550617822603450009">"முகம் காட்டித் திறத்தல் அம்சத்தை அமையுங்கள்"</string>
<string name="face_setup_notification_content" msgid="5463999831057751676">"மொபைலைப் பார்ப்பதன் மூலம் அதைத் திறக்கலாம்"</string>
<string name="fingerprint_setup_notification_title" msgid="2002630611398849495">"திறக்க, மேலும் பல வழிகளை அமையுங்கள்"</string>
<string name="fingerprint_setup_notification_content" msgid="205578121848324852">"கைரேகையைச் சேர்க்கத் தட்டுங்கள்"</string>
@@ -646,16 +646,16 @@
<string name="face_error_timeout" msgid="522924647742024699">"\'முகம் காட்டித் திறத்தலை\' மீண்டும் முயலவும்."</string>
<string name="face_error_no_space" msgid="5649264057026021723">"புதிய முகங்களைச் சேர்க்க இயலவில்லை. பழையது ஒன்றை நீக்கவும்."</string>
<string name="face_error_canceled" msgid="2164434737103802131">"முக அங்கீகாரச் செயல்பாடு ரத்துசெய்யப்பட்டது."</string>
- <string name="face_error_user_canceled" msgid="8553045452825849843">"\'முகம் காட்டித் திறத்தல்\' பயனரால் ரத்துசெய்யப்பட்டது."</string>
+ <string name="face_error_user_canceled" msgid="8553045452825849843">"பயனர் \'முகம் காட்டித் திறத்தல்\' அம்சத்தை ரத்துசெய்தார்."</string>
<string name="face_error_lockout" msgid="7864408714994529437">"பலமுறை முயன்றுவிட்டீர்கள். பிறகு முயலவும்."</string>
- <string name="face_error_lockout_permanent" msgid="8277853602168960343">"பலமுறை முயன்றுவிட்டீர்கள். \'முகம் காட்டித் திறத்தல்’ முடக்கப்பட்டது."</string>
+ <string name="face_error_lockout_permanent" msgid="8277853602168960343">"பலமுறை முயன்றுவிட்டீர்கள். \'முகம் காட்டித் திறத்தல்’ அம்சம் முடக்கப்பட்டது."</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"முகத்தைச் சரிபார்க்க இயலவில்லை. மீண்டும் முயலவும்."</string>
- <string name="face_error_not_enrolled" msgid="7369928733504691611">"’முகம் காட்டித் திறத்தலை’ நீங்கள் அமைக்கவில்லை."</string>
+ <string name="face_error_not_enrolled" msgid="7369928733504691611">"‘முகம் காட்டித் திறத்தல்’ அம்சத்தை நீங்கள் அமைக்கவில்லை."</string>
<string name="face_error_hw_not_present" msgid="1070600921591729944">"இந்த சாதனத்தில் ’முகம் காட்டித் திறத்தல்’ ஆதரிக்கப்படவில்லை."</string>
<string name="face_error_security_update_required" msgid="5076017208528750161">"சென்சார் தற்காலிகமாக முடக்கப்பட்டுள்ளது."</string>
<string name="face_name_template" msgid="3877037340223318119">"முகம் <xliff:g id="FACEID">%d</xliff:g>"</string>
<string name="face_app_setting_name" msgid="8130135875458467243">"முகம் காட்டித் திறத்தலை உபயோகி"</string>
- <string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"முகத்தையோ திரைப் பூட்டையோ பயன்படுத்து"</string>
+ <string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"முகம் காட்டித் திறத்தல் / திரைப் பூட்டைப் பயன்படுத்து"</string>
<string name="face_dialog_default_subtitle" msgid="6620492813371195429">"தொடர்வதற்கு உங்கள் முகத்தைப் பயன்படுத்துங்கள்"</string>
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"தொடர, உங்கள் முகத்தையோ திரைப் பூட்டையோ பயன்படுத்துங்கள்"</string>
<string-array name="face_error_vendor">
@@ -887,7 +887,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"மீண்டும் முயற்சிக்கவும்"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"மீண்டும் முயற்சிக்கவும்"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"எல்லா அம்சங்கள் & தரவை பெற, சாதனத்தை திறக்கவும்"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"முகம் திறப்பதற்கான அதிகபட்ச முயற்சிகள் கடந்தன"</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"முகம் காட்டித் திறத்தல் அம்சத்தை அதிகமுறை பயன்படுத்துவிட்டீர்கள்"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"சிம் கார்டு இல்லை"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"டேப்லெட்டில் சிம் கார்டு இல்லை."</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"Android TVயில் SIM கார்டு இல்லை."</string>
@@ -1022,8 +1022,7 @@
<string name="text_copied" msgid="2531420577879738860">"உரை கிளிப்போர்டிற்கு நகலெடுக்கப்பட்டது."</string>
<string name="copied" msgid="4675902854553014676">"நகலெடுக்கப்பட்டது"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> ஆப்ஸிலிருந்து <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ஒட்டப்பட்டது"</string>
- <!-- no translation found for pasted_from_clipboard (7355790625710831847) -->
- <skip />
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"கிளிப்போர்டில் இருந்து <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ஒட்டப்பட்டது"</string>
<string name="pasted_text" msgid="4298871641549173733">"நீங்கள் நகலெடுத்த உரையை <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ஆப்ஸ் ஒட்டியது"</string>
<string name="pasted_image" msgid="4729097394781491022">"நீங்கள் நகலெடுத்த படத்தை <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ஆப்ஸ் ஒட்டியது"</string>
<string name="pasted_content" msgid="646276353060777131">"நீங்கள் நகலெடுத்த உள்ளடக்கத்தை <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ஆப்ஸ் ஒட்டியது"</string>
@@ -1260,14 +1259,10 @@
<string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g>ஐத் தயார்செய்கிறது."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"ஆப்ஸ் தொடங்கப்படுகின்றன."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"துவக்குதலை முடிக்கிறது."</string>
- <!-- no translation found for fp_enrollment_powerbutton_intent_title (3385634173366119903) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_message (6582149052513682522) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_positive_button (5963520983910436791) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_negative_button (6465764183480190748) -->
- <skip />
+ <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="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>
@@ -1718,8 +1713,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"ஷார்ட்கட்டைப் பயன்படுத்து"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"நிற நேரெதிர் மாற்றம்"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"நிறத் திருத்தம்"</string>
- <!-- no translation found for one_handed_mode_feature_name (2334330034828094891) -->
- <skip />
+ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"ஒற்றைக் கைப் பயன்முறை"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"மிகக் குறைவான வெளிச்சம்"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ஒலியளவுக்கான விசைகளைப் பிடித்திருந்தீர்கள். <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ஆன் செய்யப்பட்டது."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"ஒலியளவுக்கான விசைகளைப் பிடித்திருந்தீர்கள். <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ஆஃப் செய்யப்பட்டது."</string>
@@ -1875,10 +1869,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"உங்கள் நிர்வாகி புதுப்பித்துள்ளார்"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"உங்கள் நிர்வாகி நீக்கியுள்ளார்"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"சரி"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"பேட்டரி சேமிப்பான் டார்க் தீமினை ஆன் செய்து பின்னணிச் செயல்பாடு, சில விஷுவல் எஃபெக்ட்கள், குறிப்பிட்ட அம்சங்கள், சில நெட்வொர்க் இணைப்புகள் ஆகியவற்றைக் கட்டுப்படுத்தும் அல்லது ஆஃப் செய்யும்.\n\n"<annotation id="url">"மேலும் அறிக"</annotation></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>
@@ -1981,10 +1973,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"இப்போது <xliff:g id="APP_NAME_0">%1$s</xliff:g> ஆப்ஸை உபயோகிக்க இயலாது. இதை <xliff:g id="APP_NAME_1">%2$s</xliff:g> நிர்வகிக்கிறது."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"மேலும் அறிக"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"ஆப்ஸ் இயக்கு"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"பணி ஆப்ஸை இயக்கவா?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"உங்கள் பணி ஆப்ஸுக்கும் அறிவிப்புகளுக்குமான அணுகலைப் பெறுங்கள்"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"இயக்கு"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"இந்த ஆப்ஸ் இப்போது கிடைப்பதில்லை"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸ் இப்போது கிடைப்பதில்லை."</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index 13b3e2c..8444eac 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -609,10 +609,10 @@
<string-array name="fingerprint_error_vendor">
</string-array>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"వేలిముద్ర చిహ్నం"</string>
- <string name="permlab_manageFace" msgid="4569549381889283282">"ముఖంతో అన్లాక్ చేయగల హార్డ్వేర్ నిర్వహణ"</string>
+ <string name="permlab_manageFace" msgid="4569549381889283282">"ఫేస్ అన్లాక్ చేయగల హార్డ్వేర్ను మేనేజ్ చేయడం"</string>
<string name="permdesc_manageFace" msgid="6204569688492710471">"వినియోగం కోసం ముఖ టెంప్లేట్లను జోడించే మరియు తొలగించే పద్ధతులను అమలు చేయడానికి యాప్ను అనుమతిస్తుంది."</string>
- <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"ముఖంతో అన్లాక్ చేయగల హార్డ్వేర్ వినియోగం"</string>
- <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"ప్రమాణీకరణ కోసం ముఖంతో అన్లాక్ చేయగల హార్డ్వేర్ను ఉపయోగించడానికి యాప్ను అనుమతిస్తుంది"</string>
+ <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"ఫేస్ అన్లాక్ హార్డ్వేర్ను ఉపయోగించడం"</string>
+ <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"ప్రామాణీకరణ కోసం ఫేస్తో అన్లాక్ చేయగల హార్డ్వేర్ ఉపయోగానికి యాప్ను అనుమతిస్తుంది"</string>
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"ఫేస్ అన్లాక్"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"మీ ముఖాన్ని తిరిగి నమోదు చేయండి"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"గుర్తింపును మెరుగుపరచడానికి, దయచేసి మీ ముఖంను తిరిగి నమోదు చేసుకోండి"</string>
@@ -643,19 +643,19 @@
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="5085202213036026288">"ముఖం ధృవీకరించలేరు. హార్డ్వేర్ అందుబాటులో లేదు."</string>
- <string name="face_error_timeout" msgid="522924647742024699">"ముఖంతో అన్లాక్ను మళ్లీ ప్రయత్నించండి."</string>
+ <string name="face_error_timeout" msgid="522924647742024699">"ఫేస్ అన్లాక్ను మళ్లీ ప్రయత్నించండి."</string>
<string name="face_error_no_space" msgid="5649264057026021723">"కొత్త ముఖం డేటాను నిల్వ చేయడం కాదు. మొదట పాతది తొలిగించండి."</string>
<string name="face_error_canceled" msgid="2164434737103802131">"ముఖ కార్యకలాపం రద్దయింది."</string>
- <string name="face_error_user_canceled" msgid="8553045452825849843">"ముఖంతో అన్లాక్ను వినియోగదారు రద్దు చేశారు."</string>
+ <string name="face_error_user_canceled" msgid="8553045452825849843">"ఫేస్ అన్లాక్ను యూజర్ రద్దు చేశారు."</string>
<string name="face_error_lockout" msgid="7864408714994529437">"చాలా ఎక్కువ ప్రయత్నాలు చేసారు. తర్వాత మళ్లీ ప్రయత్నించండి."</string>
- <string name="face_error_lockout_permanent" msgid="8277853602168960343">"అనేకసార్లు ప్రయత్నించారు. ముఖంతో అన్లాక్ నిలిపివేయబడింది."</string>
+ <string name="face_error_lockout_permanent" msgid="8277853602168960343">"చాలా సార్లు ప్రయత్నించారు. ఫేస్ అన్లాక్ డిజేబుల్ చేయబడింది."</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"ముఖం ధృవీకరించలేకపోయింది. మళ్లీ ప్రయత్నించండి."</string>
- <string name="face_error_not_enrolled" msgid="7369928733504691611">"మీరు ముఖంతో అన్లాక్ను సెటప్ చేయలేదు."</string>
- <string name="face_error_hw_not_present" msgid="1070600921591729944">"ఈ పరికరంలో ముఖంతో అన్లాక్ను ఉపయోగించడానికి మద్దతు లేదు."</string>
+ <string name="face_error_not_enrolled" msgid="7369928733504691611">"మీరు ఫేస్ అన్లాక్ను సెటప్ చేయలేదు."</string>
+ <string name="face_error_hw_not_present" msgid="1070600921591729944">"ఈ పరికరంలో ఫేస్ అన్లాక్ను ఉపయోగించడానికి సపోర్ట్ లేదు."</string>
<string name="face_error_security_update_required" msgid="5076017208528750161">"సెన్సార్ తాత్కాలికంగా డిజేబుల్ చేయబడింది."</string>
<string name="face_name_template" msgid="3877037340223318119">"ముఖ <xliff:g id="FACEID">%d</xliff:g>"</string>
<string name="face_app_setting_name" msgid="8130135875458467243">"ఫేస్ అన్లాక్ను ఉపయోగించండి"</string>
- <string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"ముఖం లేదా స్క్రీన్ లాక్ను ఉపయోగించండి"</string>
+ <string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"ఫేస్ లేదా స్క్రీన్ లాక్ను ఉపయోగించండి"</string>
<string name="face_dialog_default_subtitle" msgid="6620492813371195429">"కొనసాగించడానికి మీ ముఖాన్ని ఉపయోగించండి"</string>
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"కొనసాగించడానికి మీ ముఖం లేదా స్క్రీన్ లాక్ను ఉపయోగించండి"</string>
<string-array name="face_error_vendor">
@@ -887,7 +887,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"మళ్లీ ప్రయత్నించండి"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"మళ్లీ ప్రయత్నించండి"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"అన్ని లక్షణాలు మరియు డేటా కోసం అన్లాక్ చేయండి"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"ముఖంతో అన్లాక్ ప్రయత్నాల గరిష్ట పరిమితి మించిపోయారు"</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"ఫేస్ అన్లాక్ ప్రయత్నాల గరిష్ఠ పరిమితిని మించిపోయారు"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"సిమ్ కార్డు లేదు"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"టాబ్లెట్లో సిమ్ కార్డు లేదు."</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"మీ Android TV పరికరంలో SIM కార్డ్ లేదు."</string>
@@ -1022,8 +1022,7 @@
<string name="text_copied" msgid="2531420577879738860">"వచనం క్లిప్బోర్డ్కు కాపీ చేయబడింది."</string>
<string name="copied" msgid="4675902854553014676">"కాపీ చేయబడింది"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> నుండి పేస్ట్ చేయబడింది"</string>
- <!-- no translation found for pasted_from_clipboard (7355790625710831847) -->
- <skip />
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"మీ క్లిప్బోర్డ్ నుండి <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> పేస్ట్ చేయబడింది"</string>
<string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> మీరు కాపీ చేసిన టెక్స్ట్ను పేస్ట్ చేసింది"</string>
<string name="pasted_image" msgid="4729097394781491022">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> మీరు కాపీ చేసిన ఇమేజ్ను పేస్ట్ చేసింది"</string>
<string name="pasted_content" msgid="646276353060777131">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> మీరు కాపీ చేసిన కంటెంట్ను పేస్ట్ చేసింది"</string>
@@ -1260,14 +1259,10 @@
<string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g>ని సిద్ధం చేస్తోంది."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"అనువర్తనాలను ప్రారంభిస్తోంది."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"బూట్ను ముగిస్తోంది."</string>
- <!-- no translation found for fp_enrollment_powerbutton_intent_title (3385634173366119903) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_message (6582149052513682522) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_positive_button (5963520983910436791) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_negative_button (6465764183480190748) -->
- <skip />
+ <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="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>
@@ -1566,8 +1561,8 @@
<string name="keyboardview_keycode_enter" msgid="168054869339091055">"Enter"</string>
<string name="activitychooserview_choose_application" msgid="3500574466367891463">"యాప్ను ఎంచుకోండి"</string>
<string name="activitychooserview_choose_application_error" msgid="6937782107559241734">"<xliff:g id="APPLICATION_NAME">%s</xliff:g>ని ప్రారంభించడం సాధ్యపడలేదు"</string>
- <string name="shareactionprovider_share_with" msgid="2753089758467748982">"వీటితో భాగస్వామ్యం చేయండి"</string>
- <string name="shareactionprovider_share_with_application" msgid="4902832247173666973">"<xliff:g id="APPLICATION_NAME">%s</xliff:g>తో భాగస్వామ్యం చేయండి"</string>
+ <string name="shareactionprovider_share_with" msgid="2753089758467748982">"వీటితో షేర్ చేయండి"</string>
+ <string name="shareactionprovider_share_with_application" msgid="4902832247173666973">"<xliff:g id="APPLICATION_NAME">%s</xliff:g>తో షేర్ చేయండి"</string>
<string name="content_description_sliding_handle" msgid="982510275422590757">"స్లైడింగ్ హ్యాండిల్. తాకి, ఆపై నొక్కి ఉంచండి."</string>
<string name="description_target_unlock_tablet" msgid="7431571180065859551">"అన్లాక్ చేయడానికి స్వైప్ చేయండి."</string>
<string name="action_bar_home_description" msgid="1501655419158631974">"హోమ్కు నావిగేట్ చేయండి"</string>
@@ -1611,7 +1606,7 @@
<string name="sha1_fingerprint" msgid="2339915142825390774">"SHA-1 వేలిముద్ర:"</string>
<string name="activity_chooser_view_see_all" msgid="3917045206812726099">"అన్నీ చూడండి"</string>
<string name="activity_chooser_view_dialog_title_default" msgid="8880731437191978314">"కార్యాచరణను ఎంచుకోండి"</string>
- <string name="share_action_provider_share_with" msgid="1904096863622941880">"వీటితో భాగస్వామ్యం చేయండి"</string>
+ <string name="share_action_provider_share_with" msgid="1904096863622941880">"వీటితో షేర్ చేయండి"</string>
<string name="sending" msgid="206925243621664438">"పంపుతోంది..."</string>
<string name="launchBrowserDefault" msgid="6328349989932924119">"బ్రౌజర్ను ప్రారంభించాలా?"</string>
<string name="SetupCallDefault" msgid="5581740063237175247">"కాల్ను ఆమోదించాలా?"</string>
@@ -1718,8 +1713,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"సత్వరమార్గాన్ని ఉపయోగించు"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"కలర్ మార్పిడి"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"కలర్ సరిచేయడం"</string>
- <!-- no translation found for one_handed_mode_feature_name (2334330034828094891) -->
- <skip />
+ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"వన్-హ్యాండెడ్ మోడ్"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"కాంతిని మరింత డిమ్ చేయడం"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"వాల్యూమ్ కీలు నొక్కి ఉంచబడ్డాయి. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ఆన్ చేయబడింది"</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"వాల్యూమ్ కీలు నొక్కి ఉంచబడ్డాయి. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ఆఫ్ చేయబడింది"</string>
@@ -1875,10 +1869,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"మీ నిర్వాహకులు నవీకరించారు"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"మీ నిర్వాహకులు తొలగించారు"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"సరే"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"బ్యాటరీ సేవర్ ముదురు రంగు రూపాన్ని ఆన్ చేసి, బ్యాక్గ్రౌండ్ యాక్టివిటీ, కొన్ని విజువల్ ఎఫెక్ట్లు, నిర్దిష్ట ఫీచర్లు, ఇంకా కొన్ని నెట్వర్క్ కనెక్షన్లను పరిమితం చేస్తుంది లేదా ఆఫ్ చేస్తుంది.\n\n"<annotation id="url">"మరింత తెలుసుకోండి"</annotation></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>
@@ -1981,10 +1973,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ప్రస్తుతం అందుబాటులో లేదు. ఇది <xliff:g id="APP_NAME_1">%2$s</xliff:g> ద్వారా నిర్వహించబడుతుంది."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"మరింత తెలుసుకోండి"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"యాప్పై వున్న పాజ్ను తొలగించండి"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"వర్క్ యాప్లను ఆన్ చేయాలా?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"మీ వర్క్ యాప్లు, నోటిఫికేషన్లకు యాక్సెస్ను పొందండి"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"ఆన్ చేయి"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"యాప్ అందుబాటులో లేదు"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ప్రస్తుతం అందుబాటులో లేదు."</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 663fc84..cc616f0 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1022,8 +1022,7 @@
<string name="text_copied" msgid="2531420577879738860">"คัดลอกข้อความไปยังคลิปบอร์ด"</string>
<string name="copied" msgid="4675902854553014676">"คัดลอกแล้ว"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"วาง <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> จาก <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> แล้ว"</string>
- <!-- no translation found for pasted_from_clipboard (7355790625710831847) -->
- <skip />
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"วาง <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> จากคลิปบอร์ดแล้ว"</string>
<string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> วางข้อความที่คุณคัดลอก"</string>
<string name="pasted_image" msgid="4729097394781491022">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> วางรูปภาพที่คุณคัดลอก"</string>
<string name="pasted_content" msgid="646276353060777131">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> วางเนื้อหาที่คุณคัดลอก"</string>
@@ -1260,14 +1259,10 @@
<string name="android_preparing_apk" msgid="589736917792300956">"กำลังเตรียม <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"กำลังเริ่มต้นแอปพลิเคชัน"</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"เสร็จสิ้นการบูต"</string>
- <!-- no translation found for fp_enrollment_powerbutton_intent_title (3385634173366119903) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_message (6582149052513682522) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_positive_button (5963520983910436791) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_negative_button (6465764183480190748) -->
- <skip />
+ <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="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>
@@ -1874,10 +1869,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"อัปเดตโดยผู้ดูแลระบบ"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"ลบโดยผู้ดูแลระบบ"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ตกลง"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"โหมดประหยัดแบตเตอรี่จะเปิดธีมมืดและจำกัดหรือปิดกิจกรรมในเบื้องหลัง เอฟเฟกต์ภาพบางอย่าง ฟีเจอร์บางส่วน และการเชื่อมต่อบางเครือข่าย\n\n"<annotation id="url">"ดูข้อมูลเพิ่มเติม"</annotation></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>
@@ -1980,10 +1973,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"เปิด <xliff:g id="APP_NAME_0">%1$s</xliff:g> ไม่ได้ในขณะนี้ แอปนี้จัดการโดย <xliff:g id="APP_NAME_1">%2$s</xliff:g>"</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"ดูข้อมูลเพิ่มเติม"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"ยกเลิกการหยุดแอปชั่วคราว"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"เปิดแอปงานใช่ไหม"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"รับสิทธิ์เข้าถึงแอปงานและการแจ้งเตือนต่างๆ"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"เปิด"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"แอปไม่พร้อมใช้งาน"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ไม่พร้อมใช้งานในขณะนี้"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index e26ce1c..f3d5fc4 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -609,14 +609,14 @@
<string-array name="fingerprint_error_vendor">
</string-array>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Icon ng fingerprint"</string>
- <string name="permlab_manageFace" msgid="4569549381889283282">"pamahalaan ang hardware ng face unlock"</string>
+ <string name="permlab_manageFace" msgid="4569549381889283282">"pamahalaan ang hardware ng pag-unlock gamit ang mukha"</string>
<string name="permdesc_manageFace" msgid="6204569688492710471">"Pumapayag na mag-invoke ang app ng paraang magdagdag at mag-delete ng template ng mukha."</string>
- <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"gamitin ang hardware ng face unlock"</string>
- <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Pinapayagan ang app na gamitin ang hardware ng face unlock para sa pag-authenticate"</string>
- <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Face unlock"</string>
+ <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"gamitin ang hardware ng Pag-unlock Gamit ang Mukha"</string>
+ <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Pinapayagan ang app na gamitin ang hardware ng Pag-unlock Gamit ang Mukha para sa pag-authenticate"</string>
+ <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Pag-unlock Gamit ang Mukha"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"I-enroll ulit ang iyong mukha"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Para mapahusay ang pagkilala, paki-enroll ulit ang iyong mukha"</string>
- <string name="face_setup_notification_title" msgid="550617822603450009">"I-set up ang face unlock"</string>
+ <string name="face_setup_notification_title" msgid="550617822603450009">"I-set up ang pag-unlock gamit ang mukha"</string>
<string name="face_setup_notification_content" msgid="5463999831057751676">"I-unlock ang iyong telepono sa pamamagitan ng pagtingin dito"</string>
<string name="fingerprint_setup_notification_title" msgid="2002630611398849495">"Mag-set up ng higit pang paraan para mag-unlock"</string>
<string name="fingerprint_setup_notification_content" msgid="205578121848324852">"I-tap para magdagdag ng fingerprint"</string>
@@ -643,18 +643,18 @@
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="5085202213036026288">"Di ma-verify ang mukha. Di available ang hardware."</string>
- <string name="face_error_timeout" msgid="522924647742024699">"Subukan ulit ang face unlock."</string>
+ <string name="face_error_timeout" msgid="522924647742024699">"Subukan ulit ang pag-unlock gamit ang mukha."</string>
<string name="face_error_no_space" msgid="5649264057026021723">"Hindi ma-store ang data ng mukha. Mag-delete muna ng iba."</string>
<string name="face_error_canceled" msgid="2164434737103802131">"Nakansela ang operation kaugnay ng mukha."</string>
- <string name="face_error_user_canceled" msgid="8553045452825849843">"Kinansela ng user ang face unlock."</string>
+ <string name="face_error_user_canceled" msgid="8553045452825849843">"Kinansela ng user ang pag-unlock gamit ang mukha."</string>
<string name="face_error_lockout" msgid="7864408714994529437">"Masyadong maraming pagsubok. Subukang muli mamaya."</string>
- <string name="face_error_lockout_permanent" msgid="8277853602168960343">"Masyadong maraming pagsubok. Na-disable ang face unlock."</string>
+ <string name="face_error_lockout_permanent" msgid="8277853602168960343">"Masyadong maraming pagsubok. Na-disable ang pag-unlock gamit ang mukha."</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"Hindi ma-verify ang mukha. Subukang muli."</string>
- <string name="face_error_not_enrolled" msgid="7369928733504691611">"Hindi mo pa nase-set up ang face unlock."</string>
- <string name="face_error_hw_not_present" msgid="1070600921591729944">"Hindi sinusuportahan ang face unlock sa device na ito."</string>
+ <string name="face_error_not_enrolled" msgid="7369928733504691611">"Hindi mo pa nase-set up ang pag-unlock gamit ang mukha."</string>
+ <string name="face_error_hw_not_present" msgid="1070600921591729944">"Hindi sinusuportahan ang pag-unlock gamit ang mukha sa device na ito."</string>
<string name="face_error_security_update_required" msgid="5076017208528750161">"Pansamantalang na-disable ang sensor."</string>
<string name="face_name_template" msgid="3877037340223318119">"Mukha <xliff:g id="FACEID">%d</xliff:g>"</string>
- <string name="face_app_setting_name" msgid="8130135875458467243">"Gumamit ng face unlock"</string>
+ <string name="face_app_setting_name" msgid="8130135875458467243">"Gumamit ng pag-unlock gamit ang mukha"</string>
<string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"Gumamit ng mukha o lock ng screen"</string>
<string name="face_dialog_default_subtitle" msgid="6620492813371195429">"Gamitin ang iyong mukha para magpatuloy"</string>
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Gamitin ang iyong mukha o lock ng screen para magpatuloy"</string>
@@ -887,7 +887,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Subukang muli"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"Subukang muli"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"I-unlock para sa lahat ng feature at data"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Nalagpasan na ang maximum na mga pagtatangka sa Face Unlock"</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Nalagpasan na ang maximum na mga pagtatangka sa Pag-unlock Gamit ang Mukha"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"Walang SIM card"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"Walang SIM card sa tablet."</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"Walang SIM card sa iyong Android TV device."</string>
@@ -957,7 +957,7 @@
<string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"Palakihin ang bahagi ng pag-unlock."</string>
<string name="keyguard_accessibility_slide_unlock" msgid="2968195219692413046">"Pag-unlock ng slide."</string>
<string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"Pag-unlock ng pattern."</string>
- <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"Face unlock."</string>
+ <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"Pag-unlock gamit ang mukha."</string>
<string name="keyguard_accessibility_pin_unlock" msgid="4020864007967340068">"Pag-unlock ng pin."</string>
<string name="keyguard_accessibility_sim_pin_unlock" msgid="4895939120871890557">"Pag-unlock ng Pin ng Sim."</string>
<string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"Pag-unlock ng Puk ng Sim."</string>
@@ -1022,8 +1022,7 @@
<string name="text_copied" msgid="2531420577879738860">"Nakopya ang teksto sa clipboard."</string>
<string name="copied" msgid="4675902854553014676">"Nakopya"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"Na-paste ang <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> mula sa <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>"</string>
- <!-- no translation found for pasted_from_clipboard (7355790625710831847) -->
- <skip />
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"Na-paste ang <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> mula sa iyong clipboard"</string>
<string name="pasted_text" msgid="4298871641549173733">"Nag-paste ang <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ng text na nakopya mo"</string>
<string name="pasted_image" msgid="4729097394781491022">"Nag-paste ang <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ng larawang nakopya mo"</string>
<string name="pasted_content" msgid="646276353060777131">"Nag-paste ang <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> ng content na nakopya mo"</string>
@@ -1260,14 +1259,10 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Ihinahanda ang <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Sinisimulan ang apps."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Pagtatapos ng pag-boot."</string>
- <!-- no translation found for fp_enrollment_powerbutton_intent_title (3385634173366119903) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_message (6582149052513682522) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_positive_button (5963520983910436791) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_negative_button (6465764183480190748) -->
- <skip />
+ <string name="fp_enrollment_powerbutton_intent_title" msgid="3385634173366119903">"I-off ang screen?"</string>
+ <string name="fp_enrollment_powerbutton_intent_message" msgid="6582149052513682522">"Habang sine-set up ang iyong fingerprint, pinindot mo ang Power button.\n\nKaraniwan nitong ino-off ang iyong screen."</string>
+ <string name="fp_enrollment_powerbutton_intent_positive_button" msgid="5963520983910436791">"I-off"</string>
+ <string name="fp_enrollment_powerbutton_intent_negative_button" msgid="6465764183480190748">"Kanselahin"</string>
<string name="heavy_weight_notification" msgid="8382784283600329576">"Tumatakbo ang <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="heavy_weight_notification_detail" msgid="6802247239468404078">"Mag-tap upang bumalik sa laro"</string>
<string name="heavy_weight_switcher_title" msgid="3861984210040100886">"Pumili ng laro"</string>
@@ -1718,8 +1713,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Gamitin ang Shortcut"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Pag-invert ng Kulay"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Pagwawasto ng Kulay"</string>
- <!-- no translation found for one_handed_mode_feature_name (2334330034828094891) -->
- <skip />
+ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"One-Hand mode"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Extra dim"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Pinindot nang matagal ang volume keys. Na-on ang <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Pinindot nang matagal ang volume keys. Na-off ang <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
@@ -1875,10 +1869,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Na-update ng iyong admin"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Na-delete ng iyong admin"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"Ino-on ng Pantipid ng Baterya ang Madilim na tema at nililimitahan o ino-off nito ang aktibidad sa background, ilang visual effect, ilang partikular na feature, at ilang koneksyon sa network.\n\n"<annotation id="url">"Matuto pa"</annotation></string>
+ <string name="battery_saver_description" msgid="8518809702138617167">"Ino-on ng Pantipid ng Baterya ang Madilim na tema at nililimitahan o ino-off nito ang aktibidad sa background, ilang visual effect, ilang partikular na feature, at ilang koneksyon sa network."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Upang makatulong na mabawasan ang paggamit ng data, pinipigilan ng Data Saver ang ilang app na magpadala o makatanggap ng data sa background. Maaaring mag-access ng data ang isang app na ginagamit mo sa kasalukuyan, ngunit mas bihira na nito magagawa iyon. Halimbawa, maaaring hindi lumabas ang mga larawan hangga\'t hindi mo nata-tap ang mga ito."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"I-on ang Data Saver?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"I-on"</string>
@@ -1981,10 +1973,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"Hindi available ang <xliff:g id="APP_NAME_0">%1$s</xliff:g> sa ngayon. Pinamamahalaan ito ng <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"Matuto pa"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"I-unpause ang app"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"I-on ang app para sa trabaho?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"Makakuha ng access sa iyong mga app para sa trabaho at notification"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"I-on"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"Hindi available ang app"</string>
<string name="app_blocked_message" msgid="542972921087873023">"Hindi available sa ngayon ang <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 9c4a4d4..8c1561c 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -957,7 +957,7 @@
<string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"Kilit açma alanını genişletin."</string>
<string name="keyguard_accessibility_slide_unlock" msgid="2968195219692413046">"Kaydırarak kilit açma."</string>
<string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"Desenle kilit açma."</string>
- <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"Yüzle kilit açma."</string>
+ <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"Yüzle tanıma kilidi."</string>
<string name="keyguard_accessibility_pin_unlock" msgid="4020864007967340068">"Pin koduyla kilit açma."</string>
<string name="keyguard_accessibility_sim_pin_unlock" msgid="4895939120871890557">"SIM PIN kilidini açın."</string>
<string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"SIM PUK kilidini açın."</string>
@@ -1022,8 +1022,7 @@
<string name="text_copied" msgid="2531420577879738860">"Metin panoya kopyalandı."</string>
<string name="copied" msgid="4675902854553014676">"Kopyalandı"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> uygulaması <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> kaynağından yapıştırdı"</string>
- <!-- no translation found for pasted_from_clipboard (7355790625710831847) -->
- <skip />
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>, panonuzdakini yapıştırdı"</string>
<string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>, kopyaladığınız metni yapıştırdı"</string>
<string name="pasted_image" msgid="4729097394781491022">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>, kopyaladığınız resmi yapıştırdı"</string>
<string name="pasted_content" msgid="646276353060777131">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>, kopyaladığınız içeriği yapıştırdı"</string>
@@ -1260,14 +1259,10 @@
<string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> hazırlanıyor."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Uygulamalar başlatılıyor"</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Açılış tamamlanıyor."</string>
- <!-- no translation found for fp_enrollment_powerbutton_intent_title (3385634173366119903) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_message (6582149052513682522) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_positive_button (5963520983910436791) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_negative_button (6465764183480190748) -->
- <skip />
+ <string name="fp_enrollment_powerbutton_intent_title" msgid="3385634173366119903">"Ekran kapatılsın mı?"</string>
+ <string name="fp_enrollment_powerbutton_intent_message" msgid="6582149052513682522">"Parmak izinizi ayarlarken Güç düğmesine bastınız.\n\nBu hareket genellikle ekranınızın kapanmasına neden olur."</string>
+ <string name="fp_enrollment_powerbutton_intent_positive_button" msgid="5963520983910436791">"Kapat"</string>
+ <string name="fp_enrollment_powerbutton_intent_negative_button" msgid="6465764183480190748">"İptal"</string>
<string name="heavy_weight_notification" msgid="8382784283600329576">"<xliff:g id="APP">%1$s</xliff:g> çalışıyor"</string>
<string name="heavy_weight_notification_detail" msgid="6802247239468404078">"Oyuna geri dönmek için dokunun"</string>
<string name="heavy_weight_switcher_title" msgid="3861984210040100886">"Oyun seçin"</string>
@@ -1718,8 +1713,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Kısayolu Kullan"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Rengi Ters Çevirme"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Renk Düzeltme"</string>
- <!-- no translation found for one_handed_mode_feature_name (2334330034828094891) -->
- <skip />
+ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Tek El modu"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Ekstra loş"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Ses tuşlarını basılı tuttunuz. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> açıldı."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Ses tuşlarını basılı tuttunuz. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> kapatıldı."</string>
@@ -1875,10 +1869,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Yöneticiniz tarafından güncellendi"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Yöneticiniz tarafından silindi"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"Tamam"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"Pil Tasarrufu, Koyu temayı açıp arka plan etkinliğini, bazı görsel efektleri, belirli özellikleri ve bazı ağ bağlantılarını sınırlandırır veya kapatır.\n\n"<annotation id="url">"Daha fazla bilgi"</annotation></string>
+ <string name="battery_saver_description" msgid="8518809702138617167">"Pil Tasarrufu, Koyu temayı açıp arka plan etkinliğini, bazı görsel efektleri, belirli özellikleri ve bazı ağ bağlantılarını sınırlandırır veya kapatır."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Veri kullanımını azaltmaya yardımcı olması için Veri Tasarrufu, bazı uygulamaların arka planda veri göndermesini veya almasını engeller. Kullanmakta olduğunuz bir uygulama veri bağlantısına erişebilir, ancak bunu daha seyrek yapabilir. Bu durumda örneğin, siz resimlere dokunmadan resimler görüntülenmez."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Veri Tasarrufu açılsın mı?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"Aç"</string>
@@ -1981,10 +1973,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> uygulaması şu anda kullanılamıyor. Uygulamanın kullanım durumu <xliff:g id="APP_NAME_1">%2$s</xliff:g> tarafından yönetiliyor."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"Daha fazla bilgi"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Uygulamanın duraklatmasını kaldır"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"İş uygulamaları açılsın mı?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"İş uygulamalarınıza ve bildirimlerinize erişin"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Aç"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"Uygulama kullanılamıyor"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> uygulaması şu anda kullanılamıyor."</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index bfac264..1b0fc49 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -615,10 +615,10 @@
<string-array name="fingerprint_error_vendor">
</string-array>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Значок відбитка пальця"</string>
- <string name="permlab_manageFace" msgid="4569549381889283282">"керувати апаратним забезпечення для Фейсконтролю"</string>
+ <string name="permlab_manageFace" msgid="4569549381889283282">"керувати апаратним забезпечення фейсконтролю"</string>
<string name="permdesc_manageFace" msgid="6204569688492710471">"Додаток може активувати способи додавання й видалення шаблонів облич."</string>
<string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"використовувати апаратне забезпечення для Фейсконтролю"</string>
- <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Додаток може використовувати апаратне забезпечення для Фейсконтролю"</string>
+ <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Додаток зможе використовувати для автентифікації апаратне забезпечення фейсконтролю"</string>
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Фейсконтроль"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Повторно проскануйте обличчя"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Повторно проскануйте обличчя для ефективнішого розпізнавання"</string>
@@ -649,15 +649,15 @@
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="5085202213036026288">"Не вдається перевірити обличчя. Апаратне забезпечення недоступне."</string>
- <string name="face_error_timeout" msgid="522924647742024699">"Скористайтеся Фейсконтролем ще раз."</string>
+ <string name="face_error_timeout" msgid="522924647742024699">"Спробуйте скористатися фейсконтролем ще раз."</string>
<string name="face_error_no_space" msgid="5649264057026021723">"Не вдається зберегти нові дані про обличчя. Видаліть старі."</string>
<string name="face_error_canceled" msgid="2164434737103802131">"Дію з обличчям скасовано."</string>
- <string name="face_error_user_canceled" msgid="8553045452825849843">"Користувач скасував Фейсконтроль."</string>
+ <string name="face_error_user_canceled" msgid="8553045452825849843">"Фейсконтроль: користувач скасував операцію."</string>
<string name="face_error_lockout" msgid="7864408714994529437">"Забагато спроб. Повторіть пізніше."</string>
<string name="face_error_lockout_permanent" msgid="8277853602168960343">"Забагато спроб. Фейсконтроль вимкнено."</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"Не вдається перевірити обличчя. Повторіть спробу."</string>
- <string name="face_error_not_enrolled" msgid="7369928733504691611">"Ви не налаштували Фейсконтроль"</string>
- <string name="face_error_hw_not_present" msgid="1070600921591729944">"На цьому пристрої не підтримується Фейсконтроль."</string>
+ <string name="face_error_not_enrolled" msgid="7369928733504691611">"Ви не налаштували фейсконтроль"</string>
+ <string name="face_error_hw_not_present" msgid="1070600921591729944">"На цьому пристрої не підтримується фейсконтроль."</string>
<string name="face_error_security_update_required" msgid="5076017208528750161">"Датчик тимчасово вимкнено."</string>
<string name="face_name_template" msgid="3877037340223318119">"Обличчя <xliff:g id="FACEID">%d</xliff:g>"</string>
<string name="face_app_setting_name" msgid="8130135875458467243">"Доступ через фейсконтроль"</string>
@@ -1028,8 +1028,7 @@
<string name="text_copied" msgid="2531420577879738860">"Текст скопійов. в буф. обм."</string>
<string name="copied" msgid="4675902854553014676">"Скопійовано"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"Дані з додатка <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> вставлено в <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for pasted_from_clipboard (7355790625710831847) -->
- <skip />
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"Дані з буфера обміну вставлено в додатку <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>"</string>
<string name="pasted_text" msgid="4298871641549173733">"Скопійований текст вставлено в додатку <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>"</string>
<string name="pasted_image" msgid="4729097394781491022">"Скопійоване зображення вставлено в додатку <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>"</string>
<string name="pasted_content" msgid="646276353060777131">"Скопійований контент вставлено в додатку <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>"</string>
@@ -1300,14 +1299,10 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Підготовка додатка <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Запуск програм."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Завершення завантаження."</string>
- <!-- no translation found for fp_enrollment_powerbutton_intent_title (3385634173366119903) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_message (6582149052513682522) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_positive_button (5963520983910436791) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_negative_button (6465764183480190748) -->
- <skip />
+ <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="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>
@@ -1762,8 +1757,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Використовувати ярлик"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Інверсія кольорів"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Корекція кольорів"</string>
- <!-- no translation found for one_handed_mode_feature_name (2334330034828094891) -->
- <skip />
+ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Режим керування однією рукою"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Додаткове зменшення яскравості"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Утримано клавіші гучності. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> увімкнено."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Утримано клавіші гучності. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> вимкнено."</string>
@@ -1921,10 +1915,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Оновлено адміністратором"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Видалено адміністратором"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ОК"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"У режимі енергозбереження вмикається Темна тема й обмежуються чи вимикаються дії у фоновому режимі, а також деякі візуальні ефекти, функції та з’єднання з мережами.\n\n"<annotation id="url">"Докладніше"</annotation></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>
@@ -2045,10 +2037,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"Додаток <xliff:g id="APP_NAME_0">%1$s</xliff:g> зараз недоступний. Керує додаток <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"Докладніше"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Відновити доступ до додатка"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"Увімкнути робочі додатки?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"Отримайте доступ до своїх робочих додатків і сповіщень"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Увімкнути"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"Додаток недоступний"</string>
<string name="app_blocked_message" msgid="542972921087873023">"Додаток <xliff:g id="APP_NAME">%1$s</xliff:g> зараз недоступний."</string>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index fedb557..f50ee1d 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -609,14 +609,14 @@
<string-array name="fingerprint_error_vendor">
</string-array>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"فنگر پرنٹ آئیکن"</string>
- <string name="permlab_manageFace" msgid="4569549381889283282">"چہرے کے ذریعے غیر مقفل کرنے والے ہارڈ ویئر کا نظم کریں"</string>
+ <string name="permlab_manageFace" msgid="4569549381889283282">"فیس اَنلاک والے ہارڈ ویئر کا نظم کریں"</string>
<string name="permdesc_manageFace" msgid="6204569688492710471">"ایپ کو چہرے کی تمثیلات شامل اور حذف کرنے کے طریقوں کو کالعدم قرار دینے کی اجازت دیتا ہے۔"</string>
- <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"چہرے کے ذریعے غیر مقفل کرنے والا ہارڈ ویئر استعمال کریں"</string>
- <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"ایپ کو تصدیق کے لیے چہرے کے ذریعے غیر مقفل کرنے کا ہارڈ ویئر استعمال کرنے کی اجازت دیتی ہے"</string>
- <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"چہرے کے ذریعے غیر مقفل کریں"</string>
+ <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"فیس اَنلاک والا ہارڈ ویئر استعمال کریں"</string>
+ <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"ایپ کو تصدیق کے لیے فیس اَنلاک کا ہارڈ ویئر استعمال کرنے کی اجازت دیتی ہے"</string>
+ <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"فیس اَنلاک"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"اپنے چہرے کو دوبارہ مندرج کریں"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"شناخت کو بہتر بنانے کے لیے براہ کرم اپنے چہرے کو دوبارہ مندرج کریں"</string>
- <string name="face_setup_notification_title" msgid="550617822603450009">"چہرے کے ذریعے غیر مقفل کرنا سیٹ اپ کریں"</string>
+ <string name="face_setup_notification_title" msgid="550617822603450009">"فیس اَنلاک سیٹ اپ کریں"</string>
<string name="face_setup_notification_content" msgid="5463999831057751676">"اپنے فون کی طرف دیکھ کر اسے غیر مقفل کریں"</string>
<string name="fingerprint_setup_notification_title" msgid="2002630611398849495">"غیر مقفل کرنے کے مزید طریقے سیٹ اپ کریں"</string>
<string name="fingerprint_setup_notification_content" msgid="205578121848324852">"فنگر پرنٹ شامل کرنے کیلئے تھپتھپائیں"</string>
@@ -643,19 +643,19 @@
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="5085202213036026288">"چہرے کی توثیق نہیں کی جا سکی۔ ہارڈ ویئر دستیاب نہیں ہے۔"</string>
- <string name="face_error_timeout" msgid="522924647742024699">"چہرے کے ذریعے غیر مقفل کرنے کو دوبارہ آزمائیں۔"</string>
+ <string name="face_error_timeout" msgid="522924647742024699">"فیس اَنلاک کو دوبارہ آزمائیں۔"</string>
<string name="face_error_no_space" msgid="5649264057026021723">"چہرے کا نیا ڈیٹا اسٹور نہیں کر سکتے۔ پہلے پرانا حذف کریں۔"</string>
<string name="face_error_canceled" msgid="2164434737103802131">"چہرے پر ہونے والی کارروائی منسوخ ہو گئی۔"</string>
- <string name="face_error_user_canceled" msgid="8553045452825849843">"صارف نے چہرے کے ذریعے غیر مقفل کرنے کو منسوخ کر دیا۔"</string>
+ <string name="face_error_user_canceled" msgid="8553045452825849843">"صارف نے فیس اَنلاک کو منسوخ کر دیا۔"</string>
<string name="face_error_lockout" msgid="7864408714994529437">"کافی زیادہ کوششیں کی گئیں۔ دوبارہ کوشش کریں۔"</string>
- <string name="face_error_lockout_permanent" msgid="8277853602168960343">"کافی زیادہ کوششیں۔ چہرے کے ذریعے غیر مقفل کرنا غیر فعال کر دیا گیا۔"</string>
+ <string name="face_error_lockout_permanent" msgid="8277853602168960343">"کافی زیادہ کوششیں۔ فیس اَنلاک غیر فعال کر دیا گیا۔"</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"چہرے کی توثیق نہیں کی جا سکی۔ پھر آزمائيں۔"</string>
- <string name="face_error_not_enrolled" msgid="7369928733504691611">"آپ نے بذریعہ چہرہ غیر مقفل کرنے کو سیٹ نہیں کیا ہے۔"</string>
- <string name="face_error_hw_not_present" msgid="1070600921591729944">"اس آلہ پر چہرے کے ذریعے غیر مقفل کرنا تعاون یافتہ نہیں ہے۔"</string>
+ <string name="face_error_not_enrolled" msgid="7369928733504691611">"آپ نے فیس اَنلاک کو سیٹ نہیں کیا ہے۔"</string>
+ <string name="face_error_hw_not_present" msgid="1070600921591729944">"اس آلہ پر فیس اَنلاک تعاون یافتہ نہیں ہے۔"</string>
<string name="face_error_security_update_required" msgid="5076017208528750161">"سینسر عارضی طور غیر فعال ہے۔"</string>
<string name="face_name_template" msgid="3877037340223318119">"چہرہ <xliff:g id="FACEID">%d</xliff:g>"</string>
- <string name="face_app_setting_name" msgid="8130135875458467243">"چہرے کے ذریعے غیر مقفل کرنا استعمال کریں"</string>
- <string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"چہرہ یا اسکرین لاک استعمال کریں"</string>
+ <string name="face_app_setting_name" msgid="8130135875458467243">"فیس اَنلاک استعمال کریں"</string>
+ <string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"فیس یا اسکرین لاک استعمال کریں"</string>
<string name="face_dialog_default_subtitle" msgid="6620492813371195429">"جاری رکھنے کے لیے اپنے چہرے کا استعمال کریں"</string>
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"جاری رکھنے کے لیے اپنے چہرے یا اسکرین لاک کا استعمال کریں"</string>
<string-array name="face_error_vendor">
@@ -887,7 +887,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"دوبارہ کوشش کریں"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"دوبارہ کوشش کریں"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"تمام خصوصیات اور ڈیٹا کیلئے غیر مقفل کریں"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"چہرہ کے ذریعے غیر مقفل کریں کی زیادہ سے زیادہ کوششوں سے تجاوز کرگیا"</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"فیس اَنلاک کی زیادہ سے زیادہ کوششوں سے تجاوز کرگیا"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"کوئی SIM کارڈ نہیں ہے"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"ٹیبلیٹ میں کوئی SIM کارڈ نہیں ہے۔"</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"آپ کے Android TV آلہ میں SIM کارڈ نہیں ہے۔"</string>
@@ -957,7 +957,7 @@
<string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"غیر مقفل کرنے والے علاقے کو پھیلائیں۔"</string>
<string name="keyguard_accessibility_slide_unlock" msgid="2968195219692413046">"سلائیڈ کے ذریعے غیر مقفل کریں۔"</string>
<string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"پیٹرن کے ذریعے غیر مقفل کریں۔"</string>
- <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"چہرے کے ذریعے غیر مقفل کریں۔"</string>
+ <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"فیس اَنلاک۔"</string>
<string name="keyguard_accessibility_pin_unlock" msgid="4020864007967340068">"پن کے ذریعے غیر مقفل کریں۔"</string>
<string name="keyguard_accessibility_sim_pin_unlock" msgid="4895939120871890557">"Sim پن غیر مقفل۔"</string>
<string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"Sim Puk غیر مقفل۔"</string>
@@ -1022,8 +1022,7 @@
<string name="text_copied" msgid="2531420577879738860">"متن کو کلپ بورڈ پر کاپی کیا گیا۔"</string>
<string name="copied" msgid="4675902854553014676">"کاپی ہو گیا"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> سے <xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> میں پیسٹ کیا گیا"</string>
- <!-- no translation found for pasted_from_clipboard (7355790625710831847) -->
- <skip />
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> نے آپ کے کلپ بورڈ سے پپیسٹ کر دیا"</string>
<string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> نے آپ کا کاپی کردہ ٹیکسٹ پیسٹ کر دیا"</string>
<string name="pasted_image" msgid="4729097394781491022">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> نے آپ کی کاپی کردہ ایک تصویر پیسٹ کر دی"</string>
<string name="pasted_content" msgid="646276353060777131">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> نے آپ کا کاپی کردہ مواد پیسٹ کر دیا"</string>
@@ -1260,14 +1259,10 @@
<string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> تیار ہو رہی ہے۔"</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"ایپس شروع ہو رہی ہیں۔"</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"بوٹ مکمل ہو رہا ہے۔"</string>
- <!-- no translation found for fp_enrollment_powerbutton_intent_title (3385634173366119903) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_message (6582149052513682522) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_positive_button (5963520983910436791) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_negative_button (6465764183480190748) -->
- <skip />
+ <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="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>
@@ -1718,8 +1713,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"شارٹ کٹ استعمال کریں"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"رنگوں کی تقلیب"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"رنگ کی تصحیح"</string>
- <!-- no translation found for one_handed_mode_feature_name (2334330034828094891) -->
- <skip />
+ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"ایک ہاتھ کی وضع"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"اضافی دھندلا"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"والیوم کی کلیدوں کو دبائے رکھا گیا۔ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> آن ہے۔"</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"والیوم کی کلیدوں کو دبائے رکھا گیا۔ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> آف ہے۔"</string>
@@ -1875,10 +1869,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"آپ کے منتظم کے ذریعے اپ ڈیٹ کیا گیا"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"آپ کے منتظم کے ذریعے حذف کیا گیا"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ٹھیک ہے"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"بیٹری سیور گہری تھیم کو آن کرتی ہے اور پس منظر کی سرگرمی، کچھ بصری اثرات، مخصوص خصوصیات اور کچھ نیٹ ورک کنکشنز کو محدود یا آف کرتی ہے۔\n\n"<annotation id="url">"مزید جانیں"</annotation></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>
@@ -1981,10 +1973,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ابھی دستیاب نہیں ہے۔ یہ <xliff:g id="APP_NAME_1">%2$s</xliff:g> کے زیر انتظام ہے۔"</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"مزید جانیں"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"ایپ کو غیر موقوف کریں"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"ورک ایپس آن کریں؟"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"اپنی ورک ایپس اور اطلاعات تک رسائی حاصل کریں"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"آن کریں"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"ایپ دستیاب نہیں ہے"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ابھی دستیاب نہیں ہے۔"</string>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index 8320aaf..d536056 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -887,7 +887,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Qaytadan urining"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"Qaytadan urining"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"Barcha funksiya va ma’lumotlar uchun qulfdan chiqaring"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Yuzni tanitib qulfni ochishga urinish miqdoridan oshib ketdi"</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Yuz bilan ochishga urinish miqdoridan oshib ketdi"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"SIM karta solinmagan"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"Planshetingizda SIM karta yo‘q."</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"Android TV qurilmangizda SIM karta topilmadi."</string>
@@ -957,7 +957,7 @@
<string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"Qulfni ochish maydonini kengaytirish."</string>
<string name="keyguard_accessibility_slide_unlock" msgid="2968195219692413046">"Qulfni silab ochish"</string>
<string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"Grafik kalit bilan ochish."</string>
- <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"Qulfni yuzni tanitib ochish"</string>
+ <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"Yuz bilan ochish."</string>
<string name="keyguard_accessibility_pin_unlock" msgid="4020864007967340068">"Pin qulfini ochish."</string>
<string name="keyguard_accessibility_sim_pin_unlock" msgid="4895939120871890557">"SIM kartani PIN kod bilan ochish."</string>
<string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"SIM kartani PUK kod bilan ochish."</string>
@@ -1869,8 +1869,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Administrator tomonidan yangilangan"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Administrator tomonidan o‘chirilgan"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
- <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"Quvvat tejash funksiyasi Tungi mavzuni va cheklovlarni yoqadi va fondagi harakatlar, vizual effektlar, ayrim funksiyalar va tarmoq aloqalari kabi boshqa funksiyalarni faolsizlantiradi yoki cheklaydi.\n\n"<annotation id="url">"Batafsil"</annotation></string>
- <string name="battery_saver_description" msgid="8518809702138617167">"Quvvat tejash funksiyasi Tungi mavzuni va cheklovlarni yoqadi va fondagi harakatlar, vizual effektlar, ayrim funksiyalar va tarmoq aloqalari kabi boshqa funksiyalarni faolsizlantiradi yoki cheklaydi."</string>
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"Quvvat tejash funksiyasi Tungi mavzuni va cheklovlarni yoqadi hamda fondagi harakatlar, vizual effektlar, ayrim funksiyalar va tarmoq aloqalari kabi boshqa funksiyalarni faolsizlantiradi yoki cheklaydi.\n\n"<annotation id="url">"Batafsil"</annotation></string>
+ <string name="battery_saver_description" msgid="8518809702138617167">"Quvvat tejash funksiyasi Tungi mavzuni va cheklovlarni yoqadi hamda fondagi harakatlar, vizual effektlar, ayrim funksiyalar va tarmoq aloqalari kabi boshqa funksiyalarni faolsizlantiradi yoki cheklaydi."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Trafik tejash rejimida ayrim ilovalar uchun orqa fonda internetdan foydalanish imkoniyati cheklanadi. Siz ishlatayotgan ilova zaruratga qarab internet-trafik sarflashi mumkin, biroq cheklangan miqdorda. Masalan, rasmlar ustiga bosmaguningizcha ular yuklanmaydi."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Trafik tejash yoqilsinmi?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"Yoqish"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 9ddb3a6..6841ef5 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -609,9 +609,9 @@
<string-array name="fingerprint_error_vendor">
</string-array>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Biểu tượng vân tay"</string>
- <string name="permlab_manageFace" msgid="4569549381889283282">"quản lý phần cứng mở khóa bằng khuôn mặt"</string>
+ <string name="permlab_manageFace" msgid="4569549381889283282">"quản lý phần cứng của tính năng mở khóa bằng khuôn mặt"</string>
<string name="permdesc_manageFace" msgid="6204569688492710471">"Cho phép ứng dụng gọi ra các phương pháp để thêm và xóa mẫu khuôn mặt sử dụng."</string>
- <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"sử dụng phần cứng mở khóa bằng khuôn mặt"</string>
+ <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"sử dụng phần cứng của tính năng mở khóa bằng khuôn mặt"</string>
<string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Cho phép ứng dụng dùng phần cứng mở khóa bằng khuôn mặt để tiến hành xác thực"</string>
<string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Mở khóa bằng khuôn mặt"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Đăng ký lại khuôn mặt của bạn"</string>
@@ -1022,8 +1022,7 @@
<string name="text_copied" msgid="2531420577879738860">"Đã sao chép văn bản vào bảng nhớ tạm thời."</string>
<string name="copied" msgid="4675902854553014676">"Đã sao chép"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> đã dán dữ liệu từ <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>"</string>
- <!-- no translation found for pasted_from_clipboard (7355790625710831847) -->
- <skip />
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> đã dán dữ liệu từ bảng nhớ tạm của bạn"</string>
<string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> đã dán văn bản mà bạn sao chép"</string>
<string name="pasted_image" msgid="4729097394781491022">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> đã dán một hình ảnh mà bạn sao chép"</string>
<string name="pasted_content" msgid="646276353060777131">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> đã dán nội dung mà bạn sao chép"</string>
@@ -1260,14 +1259,10 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Đang chuẩn bị <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Khởi động ứng dụng."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Hoàn tất khởi động."</string>
- <!-- no translation found for fp_enrollment_powerbutton_intent_title (3385634173366119903) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_message (6582149052513682522) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_positive_button (5963520983910436791) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_negative_button (6465764183480190748) -->
- <skip />
+ <string name="fp_enrollment_powerbutton_intent_title" msgid="3385634173366119903">"Tắt màn hình?"</string>
+ <string name="fp_enrollment_powerbutton_intent_message" msgid="6582149052513682522">"Trong khi thiết lập vân tay, bạn đã nhấn vào nút Nguồn.\n\nThông thường, thao tác này sẽ tắt màn hình."</string>
+ <string name="fp_enrollment_powerbutton_intent_positive_button" msgid="5963520983910436791">"Tắt"</string>
+ <string name="fp_enrollment_powerbutton_intent_negative_button" msgid="6465764183480190748">"Hủy"</string>
<string name="heavy_weight_notification" msgid="8382784283600329576">"<xliff:g id="APP">%1$s</xliff:g> đang hoạt động"</string>
<string name="heavy_weight_notification_detail" msgid="6802247239468404078">"Nhấn để quay lại trò chơi"</string>
<string name="heavy_weight_switcher_title" msgid="3861984210040100886">"Chọn trò chơi"</string>
@@ -1718,8 +1713,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Sử dụng phím tắt"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Đảo màu"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Chỉnh màu"</string>
- <!-- no translation found for one_handed_mode_feature_name (2334330034828094891) -->
- <skip />
+ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Chế độ một tay"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Siêu tối"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Bạn đã giữ các phím âm lượng. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> đã bật."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Bạn đã giữ các phím âm lượng. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> đã tắt."</string>
@@ -1875,10 +1869,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Do quản trị viên của bạn cập nhật"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Do quản trị viên của bạn xóa"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"Trình tiết kiệm pin sẽ bật Giao diện tối, đồng thời hạn chế hoặc tắt hoạt động chạy trong nền, một số hiệu ứng hình ảnh, các tính năng nhất định và một số kết nối mạng.\n\n"<annotation id="url">"Tìm hiểu thêm"</annotation></string>
+ <string name="battery_saver_description" msgid="8518809702138617167">"Trình tiết kiệm pin sẽ bật Giao diện tối, đồng thời hạn chế hoặc tắt hoạt động chạy trong nền, một số hiệu ứng hình ảnh, các tính năng nhất định, và một số kết nối mạng."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Để giúp giảm mức sử dụng dữ liệu, Trình tiết kiệm dữ liệu sẽ chặn một số ứng dụng gửi hoặc nhận dữ liệu trong nền. Ứng dụng mà bạn hiện sử dụng có thể dùng dữ liệu nhưng tần suất sẽ giảm. Ví dụ: hình ảnh sẽ không hiển thị cho đến khi bạn nhấn vào hình ảnh đó."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Bật Trình tiết kiệm dữ liệu?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"Bật"</string>
@@ -1981,10 +1973,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> hiện không sử dụng được. Chính sách này do <xliff:g id="APP_NAME_1">%2$s</xliff:g> quản lý."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"Tìm hiểu thêm"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Mở lại ứng dụng"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"Bật các ứng dụng công việc?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"Bạn sẽ có quyền truy cập vào các ứng dụng công việc và thông báo"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Bật"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"Ứng dụng này không dùng được"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> hiện không dùng được."</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 50324d8..51735b9 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -1022,8 +1022,7 @@
<string name="text_copied" msgid="2531420577879738860">"文本已复制到剪贴板。"</string>
<string name="copied" msgid="4675902854553014676">"已复制"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>已粘贴从<xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>复制的内容"</string>
- <!-- no translation found for pasted_from_clipboard (7355790625710831847) -->
- <skip />
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"已将剪贴板中的内容粘贴到<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>"</string>
<string name="pasted_text" msgid="4298871641549173733">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>已粘贴您复制的文字"</string>
<string name="pasted_image" msgid="4729097394781491022">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>已粘贴您复制的图片"</string>
<string name="pasted_content" msgid="646276353060777131">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>已粘贴您复制的内容"</string>
@@ -1260,14 +1259,10 @@
<string name="android_preparing_apk" msgid="589736917792300956">"正在准备升级<xliff:g id="APPNAME">%1$s</xliff:g>。"</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"正在启动应用。"</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"即将完成启动。"</string>
- <!-- no translation found for fp_enrollment_powerbutton_intent_title (3385634173366119903) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_message (6582149052513682522) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_positive_button (5963520983910436791) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_negative_button (6465764183480190748) -->
- <skip />
+ <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="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>
@@ -1874,10 +1869,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"已由您的管理员更新"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"已由您的管理员删除"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"确定"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"在省电模式下,系统会启用深色主题,并限制或关闭后台活动、某些视觉效果、特定功能和部分网络连接。\n\n"<annotation id="url">"了解详情"</annotation></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>
@@ -1980,10 +1973,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g>目前无法使用。该应用是由<xliff:g id="APP_NAME_1">%2$s</xliff:g>所管理。"</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"了解详情"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"取消暂停应用"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"要开启工作应用访问权限吗?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"获取工作应用和通知的访问权限"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"开启"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"应用无法使用"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g>目前无法使用。"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 993b1bc..44bbb2e 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -1022,8 +1022,7 @@
<string name="text_copied" msgid="2531420577879738860">"文字已複製到剪貼簿。"</string>
<string name="copied" msgid="4675902854553014676">"已複製"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> 已貼上從 <xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g> 複製的資料"</string>
- <!-- no translation found for pasted_from_clipboard (7355790625710831847) -->
- <skip />
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"已將剪貼簿內容貼到「<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>」"</string>
<string name="pasted_text" msgid="4298871641549173733">"您複製的文字已貼到「<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>」"</string>
<string name="pasted_image" msgid="4729097394781491022">"您複製的圖片已貼到「<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>」"</string>
<string name="pasted_content" msgid="646276353060777131">"您複製的內容已貼到「<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>」"</string>
@@ -1260,14 +1259,10 @@
<string name="android_preparing_apk" msgid="589736917792300956">"正在準備 <xliff:g id="APPNAME">%1$s</xliff:g>。"</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"正在啟動應用程式。"</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"啟動完成。"</string>
- <!-- no translation found for fp_enrollment_powerbutton_intent_title (3385634173366119903) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_message (6582149052513682522) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_positive_button (5963520983910436791) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_negative_button (6465764183480190748) -->
- <skip />
+ <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="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>
@@ -1874,10 +1869,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"已由您的管理員更新"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"已由您的管理員刪除"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"好"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"「省電模式」會開啟深色主題背景,並限制或關閉背景活動、部分視覺效果、特定功能和部分網絡連線。\n\n"<annotation id="url">"瞭解詳情"</annotation></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>
@@ -1980,10 +1973,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"目前無法使用 <xliff:g id="APP_NAME_0">%1$s</xliff:g>。此應用程式是由「<xliff:g id="APP_NAME_1">%2$s</xliff:g>」管理。"</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"瞭解詳情"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"取消暫停應用程式"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"要開啟工作應用程式存取權嗎?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"開啟工作應用程式和通知的存取權"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"開啟"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"無法使用應用程式"</string>
<string name="app_blocked_message" msgid="542972921087873023">"目前無法使用「<xliff:g id="APP_NAME">%1$s</xliff:g>」。"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index a45f981..51a8ef2 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -1022,8 +1022,7 @@
<string name="text_copied" msgid="2531420577879738860">"文字已複製到剪貼簿。"</string>
<string name="copied" msgid="4675902854553014676">"已複製"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"「<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>」已貼上從「<xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>」複製的資料"</string>
- <!-- no translation found for pasted_from_clipboard (7355790625710831847) -->
- <skip />
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"已將剪貼簿內容貼到「<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>」"</string>
<string name="pasted_text" msgid="4298871641549173733">"你複製的文字已貼到「<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>」"</string>
<string name="pasted_image" msgid="4729097394781491022">"你複製的圖片已貼到「<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>」"</string>
<string name="pasted_content" msgid="646276353060777131">"你複製的內容已貼到「<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g>」"</string>
@@ -1260,14 +1259,10 @@
<string name="android_preparing_apk" msgid="589736917792300956">"正在準備升級「<xliff:g id="APPNAME">%1$s</xliff:g>」。"</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"正在啟動應用程式。"</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"啟動完成。"</string>
- <!-- no translation found for fp_enrollment_powerbutton_intent_title (3385634173366119903) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_message (6582149052513682522) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_positive_button (5963520983910436791) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_negative_button (6465764183480190748) -->
- <skip />
+ <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="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>
@@ -1874,10 +1869,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"已由你的管理員更新"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"已由你的管理員刪除"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"確定"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (4877297130366222145) -->
- <skip />
- <!-- no translation found for battery_saver_description (8518809702138617167) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="4877297130366222145">"省電模式會開啟深色主題,並限制或關閉背景活動、某些視覺效果、特定功能和部分網路連線。\n\n"<annotation id="url">"瞭解詳情"</annotation></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>
@@ -1980,10 +1973,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"目前無法使用「<xliff:g id="APP_NAME_0">%1$s</xliff:g>」。這項設定是由「<xliff:g id="APP_NAME_1">%2$s</xliff:g>」管理。"</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"瞭解詳情"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"取消暫停應用程式"</string>
- <!-- no translation found for work_mode_off_title (961171256005852058) -->
- <skip />
- <!-- no translation found for work_mode_off_message (7319580997683623309) -->
- <skip />
+ <string name="work_mode_off_title" msgid="961171256005852058">"要開啟工作應用程式存取權嗎?"</string>
+ <string name="work_mode_off_message" msgid="7319580997683623309">"開啟工作應用程式和通知的存取權"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"開啟"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"應用程式無法使用"</string>
<string name="app_blocked_message" msgid="542972921087873023">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」目前無法使用。"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index b983f11..a857f9a9 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -609,14 +609,14 @@
<string-array name="fingerprint_error_vendor">
</string-array>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Isithonjana sezigxivizo zeminwe"</string>
- <string name="permlab_manageFace" msgid="4569549381889283282">"phatha izingxenyekazi zekhompuyutha ze-face unlock"</string>
+ <string name="permlab_manageFace" msgid="4569549381889283282">"phatha izingxenyekazi zekhompyutha zokuvula ngobuso"</string>
<string name="permdesc_manageFace" msgid="6204569688492710471">"Ivumela uhlelo lokusebenza ukuthi luhoxise izindlela zokungeza nokususa amathempulethi obuso azosetshenziswa."</string>
- <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"sebenzisa izingxenyekazi zekhompuyutha ze-face unlock"</string>
- <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Ivumela uhlelo lokusebenza ukuthi lusebenzise izingxenyekazi zekhompuyutha ze-face unlock ukuze kufakazelwe ubuqiniso"</string>
- <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"I-Face unlock"</string>
+ <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"sebenzisa izingxenyekazi zekhompuyutha zokuvula ngobuso"</string>
+ <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Ivumela i-app isebenzise izingxenyekazi zekhompyutha zokuvula ngobuso ukuze kuqinisekiswe"</string>
+ <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Ukuvula ngobuso"</string>
<string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Phinda ubhalise ubuso bakho"</string>
<string name="face_recalibrate_notification_content" msgid="892757485125249962">"Ukuze uthuthukise ukubonwa, sicela uphinde ubhalise ubuso bakho"</string>
- <string name="face_setup_notification_title" msgid="550617822603450009">"Setha i-face unlock"</string>
+ <string name="face_setup_notification_title" msgid="550617822603450009">"Setha ukuvula ngobuso"</string>
<string name="face_setup_notification_content" msgid="5463999831057751676">"Vula ifoni yakho ngokuyibheka"</string>
<string name="fingerprint_setup_notification_title" msgid="2002630611398849495">"Setha izindlela eziningi zokuvula"</string>
<string name="fingerprint_setup_notification_content" msgid="205578121848324852">"Thepha ukuze ungeze izigxivizo zomunwe"</string>
@@ -643,18 +643,18 @@
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="5085202213036026288">"Ayikwazi ukuqinisekisa ubuso. Izingxenyekazi zekhompyutha azitholakali."</string>
- <string name="face_error_timeout" msgid="522924647742024699">"Zama i-face unlock futhi."</string>
+ <string name="face_error_timeout" msgid="522924647742024699">"Zama ukuvula ngobuso futhi."</string>
<string name="face_error_no_space" msgid="5649264057026021723">"Ayikwazi ukulondoloza idatha yobuso. Susa endala."</string>
<string name="face_error_canceled" msgid="2164434737103802131">"Umsebenzi wobuso ukhanselwe."</string>
- <string name="face_error_user_canceled" msgid="8553045452825849843">"I-face unlock ikhanselwe umsebenzisi."</string>
+ <string name="face_error_user_canceled" msgid="8553045452825849843">"Ukuvula ngobuso kukhanselwe umsebenzisi."</string>
<string name="face_error_lockout" msgid="7864408714994529437">"Imizamo eminingi kakhulu. Zama futhi emuva kwesikhathi."</string>
- <string name="face_error_lockout_permanent" msgid="8277853602168960343">"Imizamo eminingi kakhulu. I-Face unlock ikhutshaziwe."</string>
+ <string name="face_error_lockout_permanent" msgid="8277853602168960343">"Imizamo eminingi kakhulu. Ukuvula ngobuso kukhutshaziwe."</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"Ayikwazi ukuqinisekisa ubuso. Zama futhi."</string>
- <string name="face_error_not_enrolled" msgid="7369928733504691611">"Awukakasethi i-face unlock."</string>
- <string name="face_error_hw_not_present" msgid="1070600921591729944">"I-face unlock ayisekelwe kule divayisi."</string>
+ <string name="face_error_not_enrolled" msgid="7369928733504691611">"Awukakusethi ukuvula ngobuso."</string>
+ <string name="face_error_hw_not_present" msgid="1070600921591729944">"Ukuvula ngobuso kusekelwe kule divayisi."</string>
<string name="face_error_security_update_required" msgid="5076017208528750161">"Inzwa ikhutshazwe okwesikhashana."</string>
<string name="face_name_template" msgid="3877037340223318119">"Ubuso be-<xliff:g id="FACEID">%d</xliff:g>"</string>
- <string name="face_app_setting_name" msgid="8130135875458467243">"Sebenzisa i-face unlock"</string>
+ <string name="face_app_setting_name" msgid="8130135875458467243">"Sebenzisa ukuvula ngobuso"</string>
<string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"Sebenzisa i-face lock noma ukukhiya isikrini"</string>
<string name="face_dialog_default_subtitle" msgid="6620492813371195429">"Sebenzisa ubuso bakho ukuze uqhubeke"</string>
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Sebenzisa ubuso bakho noma ukukhiya isikrini ukuze uqhubeke"</string>
@@ -887,7 +887,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Zama futhi"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"Zama futhi"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"Vulela zonke izici nedatha"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Ukuzama Kokuvula Ubuso Okuningi kudluliwe"</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Ukuzama Kokuvula ngobuso sekweqe umkhawulo"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"Alikho ikhadi le-SIM."</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"Alikho ikhadi le-SIM efonini."</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="2582768023352171073">"Ayikho i-SIM card kudivayisi yakho ye-Android TV."</string>
@@ -957,7 +957,7 @@
<string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"Nwebisa indawo yokuvula."</string>
<string name="keyguard_accessibility_slide_unlock" msgid="2968195219692413046">"Ukuvula ngokuslayida."</string>
<string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"Ukuvula ngephethini."</string>
- <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"Vula ngobuso"</string>
+ <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"Ukuvula ngobuso"</string>
<string name="keyguard_accessibility_pin_unlock" msgid="4020864007967340068">"Ukuvula ngephinikhodi."</string>
<string name="keyguard_accessibility_sim_pin_unlock" msgid="4895939120871890557">"Ukuvulwa kwephinikhodi ye-Sim."</string>
<string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"Ukuvulwa kwe-puk ye-Sim."</string>
@@ -1022,8 +1022,7 @@
<string name="text_copied" msgid="2531420577879738860">"Umbhalo ukopishwe ebhodini lokunamathisela."</string>
<string name="copied" msgid="4675902854553014676">"Kukopishiwe"</string>
<string name="pasted_from_app" msgid="5627698450808256545">"I-<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> inamathiselwe kusuka ku-<xliff:g id="SOURCE_APP_NAME">%2$s</xliff:g>"</string>
- <!-- no translation found for pasted_from_clipboard (7355790625710831847) -->
- <skip />
+ <string name="pasted_from_clipboard" msgid="7355790625710831847">"I-<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> inamathiselwe ebhodini lakho lokunamathisela"</string>
<string name="pasted_text" msgid="4298871641549173733">"U-<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> unamathisele umbhalo owukopishile"</string>
<string name="pasted_image" msgid="4729097394781491022">"U-<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> unamathisele isithombe osikopishile"</string>
<string name="pasted_content" msgid="646276353060777131">"U-<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> unamathisele okuqukethwe okukopishile"</string>
@@ -1260,14 +1259,10 @@
<string name="android_preparing_apk" msgid="589736917792300956">"Ukulungisela i-<xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Qalisa izinhlelo zokusebenza."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Qedela ukuqala kabusha."</string>
- <!-- no translation found for fp_enrollment_powerbutton_intent_title (3385634173366119903) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_message (6582149052513682522) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_positive_button (5963520983910436791) -->
- <skip />
- <!-- no translation found for fp_enrollment_powerbutton_intent_negative_button (6465764183480190748) -->
- <skip />
+ <string name="fp_enrollment_powerbutton_intent_title" msgid="3385634173366119903">"Vala isikrini?"</string>
+ <string name="fp_enrollment_powerbutton_intent_message" msgid="6582149052513682522">"Lapho usetha izigxivizo zeminwe yakho, ucindezele Inkinobho yamandla.\n\nLokhu kuvame ukuvala isikrini sakho."</string>
+ <string name="fp_enrollment_powerbutton_intent_positive_button" msgid="5963520983910436791">"Vala"</string>
+ <string name="fp_enrollment_powerbutton_intent_negative_button" msgid="6465764183480190748">"Khansela"</string>
<string name="heavy_weight_notification" msgid="8382784283600329576">"<xliff:g id="APP">%1$s</xliff:g> iyasebenza"</string>
<string name="heavy_weight_notification_detail" msgid="6802247239468404078">"Thepha ukuze ubuyele emuva kwigeyimu"</string>
<string name="heavy_weight_switcher_title" msgid="3861984210040100886">"Khetha igeyimu"</string>
@@ -1718,8 +1713,7 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Sebenzisa isinqamuleli"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Ukuguqulwa kombala"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Ukulungiswa kombala"</string>
- <!-- no translation found for one_handed_mode_feature_name (2334330034828094891) -->
- <skip />
+ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Imodi yesandla esisodwa"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Ukufiphaza okwengeziwe"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Ubambe okhiye bevolumu. I-<xliff:g id="SERVICE_NAME">%1$s</xliff:g> ivuliwe."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Ubambe okhiye bevolumu. I-<xliff:g id="SERVICE_NAME">%1$s</xliff:g> ivaliwe."</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index f0c43ff..e975938 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -9568,11 +9568,4 @@
<attr name="iconfactoryBadgeSize" format="dimension"/>
<!-- Perceptual luminance of a color, in accessibility friendly color space. From 0 to 100. -->
<attr name="lStar" format="float"/>
-
- <declare-styleable name="DisplayHashingService">
- <!-- The interval required between display hash requests. Requests made faster than this
- delay will be throttled."
- @hide @SystemApi -->
- <attr name="durationBetweenRequestsMillis" format="integer" />
- </declare-styleable>
</resources>
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 6386274..ef0dc37 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -2593,6 +2593,12 @@
<!-- The code for this component is located in the given split.
<p>NOTE: This is only applicable to instant app. -->
<attr name="splitName" />
+ <!-- Set of attribution tags that should be automatically applied to this component.
+ <p>
+ Each instance of this ContentProvider will be automatically configured with
+ Context.createAttributionContext() using the first attribution tag
+ contained here. -->
+ <attr name="attributionTags" />
</declare-styleable>
<!-- Attributes that can be supplied in an AndroidManifest.xml
@@ -2728,6 +2734,12 @@
<attr name="useAppZygote" format="boolean" />
<!-- If this is a foreground service, specify its category. -->
<attr name="foregroundServiceType" />
+ <!-- Set of attribution tags that should be automatically applied to this component.
+ <p>
+ Each instance of this Service will be automatically configured with
+ Context.createAttributionContext() using the first attribution tag
+ contained here. -->
+ <attr name="attributionTags" />
</declare-styleable>
<!-- The <code>receiver</code> tag declares an
@@ -2765,6 +2777,12 @@
<attr name="exported" />
<attr name="singleUser" />
<attr name="directBootAware" />
+ <!-- Set of attribution tags that should be automatically applied to this component.
+ <p>
+ Each instance of this BroadcastReceiver will be automatically configured with
+ Context.createAttributionContext() using the first attribution tag
+ contained here. -->
+ <attr name="attributionTags" />
</declare-styleable>
<!-- The <code>activity</code> tag declares an
@@ -2892,10 +2910,12 @@
<p> See {@link android.content.pm.ActivityInfo#FLAG_PREFER_MINIMAL_POST_PROCESSING} -->
<attr name="preferMinimalPostProcessing" format="boolean"/>
- <!-- Specify the attributionTags to be used if a permission is required due to
- {@link android.content.Context#sendBroadcast(Intent, String)} being used.
- Multiple tags can be specified separated by '|'. -->
- <attr name="attributionTags"/>
+ <!-- Set of attribution tags that should be automatically applied to this component.
+ <p>
+ Each instance of this Activity will be automatically configured with
+ Context.createAttributionContext() using the first attribution tag
+ contained here. -->
+ <attr name="attributionTags" />
<!-- Specifies whether a home sound effect should be played if the home app moves to
front after an activity with this flag set to <code>true</code>.
<p>The default value of this attribute is <code>true</code>.
@@ -2942,6 +2962,7 @@
<attr name="enabled" />
<attr name="exported" />
<attr name="parentActivityName" />
+ <attr name="attributionTags" />
</declare-styleable>
<!-- The <code>meta-data</code> tag is used to attach additional
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index aa0d23b..46a1258 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -27,6 +27,8 @@
<!-- Do not translate. Defines the slots for the right-hand side icons. That is to say, the
icons in the status bar that are not notifications. -->
<string-array name="config_statusBarIcons">
+ <item><xliff:g id="id">@string/status_bar_no_calling</xliff:g></item>
+ <item><xliff:g id="id">@string/status_bar_call_strength</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_alarm_clock</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_rotate</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_headset</xliff:g></item>
@@ -58,8 +60,6 @@
<item><xliff:g id="id">@string/status_bar_hotspot</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_mobile</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_airplane</xliff:g></item>
- <item><xliff:g id="id">@string/status_bar_no_calling</xliff:g></item>
- <item><xliff:g id="id">@string/status_bar_call_strength</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_battery</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_sensors_off</xliff:g></item>
</string-array>
@@ -1653,29 +1653,38 @@
<integer name="config_timeZoneRulesCheckRetryCount">5</integer>
<!-- Whether the geolocation time zone detection feature is enabled. Setting this to false means
- the feature cannot be used. Setting this to true means it may be used if other
- configuration allows (see provider configuration below, also compile time overlays). -->
+ the feature cannot be used. Setting this to true means system server components can be
+ tested and location time zone detection may be used if other configuration allows (see
+ location time zone provider configuration settings below). -->
<bool name="config_enableGeolocationTimeZoneDetection" translatable="false">true</bool>
- <!-- Whether the primary LocationTimeZoneProvider is enabled.
- Ignored if config_enableGeolocationTimeZoneDetection is false -->
+ <!-- Whether the primary location time zone provider is enabled.
+ This setting is ignored if config_enableGeolocationTimeZoneDetection is false.
+
+ AOSP does not configure a primary location time zone provider. -->
<bool name="config_enablePrimaryLocationTimeZoneProvider" translatable="false">false</bool>
- <!-- The package name providing the primary location time zone provider.
+
+ <!-- The package hosting the primary location time zone provider.
Only used when config_enableGeolocationTimeZoneDetection and
- enablePrimaryLocationTimeZoneProvider are true. -->
- <string name="config_primaryLocationTimeZoneProviderPackageName" translatable="false">@null</string>
+ config_enablePrimaryLocationTimeZoneProvider are true.
- <!-- Whether the secondary LocationTimeZoneProvider is enabled.
- Ignored if config_enableGeolocationTimeZoneDetection is false -->
- <bool name="config_enableSecondaryLocationTimeZoneProvider" translatable="false">true</bool>
- <!-- Package name providing the secondary location time zone provider. Used only when
- config_enableSecondaryLocationTimeZoneOverlay is false.
+ See android.service.timezone.TimeZoneProviderService for how to host location time zone
+ provider services. -->
+ <string name="config_primaryLocationTimeZoneProviderPackageName" translatable="false"></string>
- By default, set to "android" to pick up the default LocationTimeZoneProvider configured in
- the system server's AndroidManifest.xml. See the
- com.android.location.timezone.service.v1.SecondaryLocationTimeZoneProvider intent-filter
- definition there for more information. -->
- <string name="config_secondaryLocationTimeZoneProviderPackageName" translatable="false">android</string>
+ <!-- Whether the secondary location time zone provider is enabled.
+ This setting is ignored if config_enableGeolocationTimeZoneDetection is false.
+
+ AOSP does not configure a secondary location time zone provider. -->
+ <bool name="config_enableSecondaryLocationTimeZoneProvider" translatable="false">false</bool>
+
+ <!-- The package hosting the secondary location time zone provider.
+ Only used when config_enableGeolocationTimeZoneDetection and
+ config_enableSecondaryLocationTimeZoneProvider are true.
+
+ See android.service.timezone.TimeZoneProviderService for how to host location time zone
+ provider services. -->
+ <string name="config_secondaryLocationTimeZoneProviderPackageName" translatable="false"></string>
<!-- Whether to enable network location overlay which allows network location provider to be
replaced by an app at run-time. When disabled, only the
@@ -3936,6 +3945,9 @@
<!-- Handle volume keys directly in Window Manager without passing them to the foreground app -->
<bool name="config_handleVolumeKeysInWindowManager">false</bool>
+ <!-- Rely or not on hardcoded aliased streams table within AudioService -->
+ <bool name="config_handleVolumeAliasesUsingVolumeGroups">false</bool>
+
<!-- Volume level of in-call notification tone playback [0..1] -->
<item name="config_inCallNotificationVolume" format="float" type="dimen">.10</item>
@@ -4796,8 +4808,9 @@
<!-- Whether to select voice/data/sms preference without user confirmation -->
<bool name="config_voice_data_sms_auto_fallback">false</bool>
- <!-- Whether to enable the one-handed keyguard on the lock screen for wide-screen devices. -->
- <bool name="config_enableOneHandedKeyguard">false</bool>
+ <!-- Whether to enable dynamic keyguard positioning for wide screen devices (e.g. only using
+ half of the screen, to be accessible using only one hand). -->
+ <bool name="config_enableDynamicKeyguardPositioning">false</bool>
<!-- Whether to allow the caching of the SIM PIN for verification after unattended reboot -->
<bool name="config_allow_pin_storage_for_unattended_reboot">true</bool>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 641b2ad..d347b93 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -3096,8 +3096,6 @@
<!-- @hide @SystemApi -->
<public name="playHomeTransitionSound" />
<public name="lStar" />
- <!-- @hide @SystemApi -->
- <public name="durationBetweenRequestsMillis" />
<public name="showInInputMethodPicker" />
<public name="effectColor" />
<!-- @hide @TestApi -->
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index b836c4c..8f40974 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -5571,7 +5571,7 @@
<!-- Label of notification action button to learn more about the enhanced notifications [CHAR LIMIT=20] -->
<string name="nas_upgrade_notification_learn_more_action">Learn more</string>
<!-- Content of notification learn more dialog about the enhanced notifications [CHAR LIMIT=NONE] -->
- <string name="nas_upgrade_notification_learn_more_content">Enhanced notifications replaced Android Adaptive Notifications in Android 12. This feature shows suggested actions and replies, and organizes your notifications.\n\nEnhanced notifications can access notification content, including personal information like contact names and messages. This feature can also dismiss or respond to notifications, such as answering phone calls and controlling Do Not Disturb.</string>
+ <string name="nas_upgrade_notification_learn_more_content">Enhanced notifications replaced Android Adaptive Notifications in Android 12. This feature shows suggested actions and replies, and organizes your notifications.\n\nEnhanced notifications can access notification content, including personal information like contact names and messages. This feature can also dismiss or respond to notifications, such as answering phone calls, and control Do Not Disturb.</string>
<!-- Dynamic mode battery saver strings -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index d440173..5bbe415 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2962,7 +2962,6 @@
<java-symbol type="string" name="importance_from_person" />
<java-symbol type="layout" name="work_widget_mask_view" />
- <java-symbol type="id" name="work_widget_mask_frame" />
<java-symbol type="id" name="work_widget_app_icon" />
<java-symbol type="id" name="work_widget_badge_icon" />
@@ -3632,6 +3631,7 @@
<java-symbol type="array" name="config_allowedSecureInstantAppSettings" />
<java-symbol type="bool" name="config_handleVolumeKeysInWindowManager" />
+ <java-symbol type="bool" name="config_handleVolumeAliasesUsingVolumeGroups" />
<java-symbol type="dimen" name="config_inCallNotificationVolume" />
<java-symbol type="string" name="config_inCallNotificationSound" />
<java-symbol type="integer" name="config_autoGroupAtCount" />
@@ -4259,7 +4259,7 @@
<java-symbol type="bool" name="config_voice_data_sms_auto_fallback" />
- <java-symbol type="bool" name="config_enableOneHandedKeyguard" />
+ <java-symbol type="bool" name="config_enableDynamicKeyguardPositioning" />
<java-symbol type="attr" name="colorAccentPrimary" />
<java-symbol type="attr" name="colorAccentSecondary" />
diff --git a/packages/SystemUI/res/drawable/circle_green_10dp.xml b/core/tests/coretests/res/color/color_with_lstar.xml
similarity index 69%
copy from packages/SystemUI/res/drawable/circle_green_10dp.xml
copy to core/tests/coretests/res/color/color_with_lstar.xml
index 571ec62..dcc3d6d 100644
--- a/packages/SystemUI/res/drawable/circle_green_10dp.xml
+++ b/core/tests/coretests/res/color/color_with_lstar.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- ~ Copyright (C) 2020 The Android Open Source Project
+ ~ Copyright (C) 2021 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
@@ -14,9 +14,7 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size android:height="10dp"
- android:width="10dp" />
- <solid android:color="#34A853" />
-</shape>
\ No newline at end of file
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:color="#ff0000" android:lStar="50" />
+</selector>
diff --git a/core/tests/coretests/res/values/colors.xml b/core/tests/coretests/res/values/colors.xml
index f01af84..029aa0d 100644
--- a/core/tests/coretests/res/values/colors.xml
+++ b/core/tests/coretests/res/values/colors.xml
@@ -25,5 +25,6 @@
<drawable name="yellow">#ffffff00</drawable>
<color name="testcolor1">#ff00ff00</color>
<color name="testcolor2">#ffff0000</color>
+ <color name="testcolor3">#fff00000</color>
<color name="failColor">#ff0000ff</color>
</resources>
diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/SetSchemaRequestTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/SetSchemaRequestTest.java
deleted file mode 100644
index 677f4bd..0000000
--- a/core/tests/coretests/src/android/app/appsearch/external/app/SetSchemaRequestTest.java
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app.appsearch;
-
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.testng.Assert.expectThrows;
-
-import android.util.ArrayMap;
-
-import org.junit.Test;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-public class SetSchemaRequestTest {
-
- private static Collection<String> getSchemaTypesFromSetSchemaRequest(SetSchemaRequest request) {
- HashSet<String> schemaTypes = new HashSet<>();
- for (AppSearchSchema schema : request.getSchemas()) {
- schemaTypes.add(schema.getSchemaType());
- }
- return schemaTypes;
- }
-
- @Test
- public void testInvalidSchemaReferences_fromDisplayedBySystem() {
- IllegalArgumentException expected =
- expectThrows(
- IllegalArgumentException.class,
- () ->
- new SetSchemaRequest.Builder()
- .setSchemaTypeDisplayedBySystem("InvalidSchema", false)
- .build());
- assertThat(expected).hasMessageThat().contains("referenced, but were not added");
- }
-
- @Test
- public void testInvalidSchemaReferences_fromPackageVisibility() {
- IllegalArgumentException expected =
- expectThrows(
- IllegalArgumentException.class,
- () ->
- new SetSchemaRequest.Builder()
- .setSchemaTypeVisibilityForPackage(
- "InvalidSchema",
- /*visible=*/ true,
- new PackageIdentifier(
- "com.foo.package",
- /*sha256Certificate=*/ new byte[] {}))
- .build());
- assertThat(expected).hasMessageThat().contains("referenced, but were not added");
- }
-
- @Test
- public void testSetSchemaTypeDisplayedBySystem_displayed() {
- AppSearchSchema schema = new AppSearchSchema.Builder("Schema").build();
-
- // By default, the schema is displayed.
- SetSchemaRequest request = new SetSchemaRequest.Builder().addSchemas(schema).build();
- assertThat(request.getSchemasNotDisplayedBySystem()).isEmpty();
-
- request =
- new SetSchemaRequest.Builder()
- .addSchemas(schema)
- .setSchemaTypeDisplayedBySystem("Schema", true)
- .build();
- assertThat(request.getSchemasNotDisplayedBySystem()).isEmpty();
- }
-
- @Test
- public void testSetSchemaTypeDisplayedBySystem_notDisplayed() {
- AppSearchSchema schema = new AppSearchSchema.Builder("Schema").build();
- SetSchemaRequest request =
- new SetSchemaRequest.Builder()
- .addSchemas(schema)
- .setSchemaTypeDisplayedBySystem("Schema", false)
- .build();
- assertThat(request.getSchemasNotDisplayedBySystem()).containsExactly("Schema");
- }
-
- @Test
- public void testSchemaTypeVisibilityForPackage_visible() {
- AppSearchSchema schema = new AppSearchSchema.Builder("Schema").build();
-
- // By default, the schema is not visible.
- SetSchemaRequest request = new SetSchemaRequest.Builder().addSchemas(schema).build();
- assertThat(request.getSchemasVisibleToPackages()).isEmpty();
-
- PackageIdentifier packageIdentifier =
- new PackageIdentifier("com.package.foo", new byte[] {100});
- Map<String, Set<PackageIdentifier>> expectedVisibleToPackagesMap = new ArrayMap<>();
- expectedVisibleToPackagesMap.put("Schema", Collections.singleton(packageIdentifier));
-
- request =
- new SetSchemaRequest.Builder()
- .addSchemas(schema)
- .setSchemaTypeVisibilityForPackage(
- "Schema", /*visible=*/ true, packageIdentifier)
- .build();
- assertThat(request.getSchemasVisibleToPackages())
- .containsExactlyEntriesIn(expectedVisibleToPackagesMap);
- }
-
- @Test
- public void testSchemaTypeVisibilityForPackage_notVisible() {
- AppSearchSchema schema = new AppSearchSchema.Builder("Schema").build();
-
- SetSchemaRequest request =
- new SetSchemaRequest.Builder()
- .addSchemas(schema)
- .setSchemaTypeVisibilityForPackage(
- "Schema",
- /*visible=*/ false,
- new PackageIdentifier(
- "com.package.foo", /*sha256Certificate=*/ new byte[] {}))
- .build();
- assertThat(request.getSchemasVisibleToPackages()).isEmpty();
- }
-
- @Test
- public void testSchemaTypeVisibilityForPackage_deduped() throws Exception {
- AppSearchSchema schema = new AppSearchSchema.Builder("Schema").build();
-
- PackageIdentifier packageIdentifier =
- new PackageIdentifier("com.package.foo", new byte[] {100});
- Map<String, Set<PackageIdentifier>> expectedVisibleToPackagesMap = new ArrayMap<>();
- expectedVisibleToPackagesMap.put("Schema", Collections.singleton(packageIdentifier));
-
- SetSchemaRequest request =
- new SetSchemaRequest.Builder()
- .addSchemas(schema)
- // Set it visible for "Schema"
- .setSchemaTypeVisibilityForPackage(
- "Schema", /*visible=*/ true, packageIdentifier)
- // Set it visible for "Schema" again, which should be a no-op
- .setSchemaTypeVisibilityForPackage(
- "Schema", /*visible=*/ true, packageIdentifier)
- .build();
- assertThat(request.getSchemasVisibleToPackages())
- .containsExactlyEntriesIn(expectedVisibleToPackagesMap);
- }
-
- @Test
- public void testSchemaTypeVisibilityForPackage_removed() throws Exception {
- AppSearchSchema schema = new AppSearchSchema.Builder("Schema").build();
-
- SetSchemaRequest request =
- new SetSchemaRequest.Builder()
- .addSchemas(schema)
- // First set it as visible
- .setSchemaTypeVisibilityForPackage(
- "Schema",
- /*visible=*/ true,
- new PackageIdentifier(
- "com.package.foo", /*sha256Certificate=*/ new byte[] {100}))
- // Then make it not visible
- .setSchemaTypeVisibilityForPackage(
- "Schema",
- /*visible=*/ false,
- new PackageIdentifier(
- "com.package.foo", /*sha256Certificate=*/ new byte[] {100}))
- .build();
-
- // Nothing should be visible.
- assertThat(request.getSchemasVisibleToPackages()).isEmpty();
- }
-}
diff --git a/core/tests/coretests/src/android/graphics/ColorStateListTest.java b/core/tests/coretests/src/android/graphics/ColorStateListTest.java
index 1d34f938..a3d52ea 100644
--- a/core/tests/coretests/src/android/graphics/ColorStateListTest.java
+++ b/core/tests/coretests/src/android/graphics/ColorStateListTest.java
@@ -67,4 +67,10 @@
int defaultColor = mResources.getColor(R.color.color_no_default);
assertEquals(mResources.getColor(R.color.testcolor1), defaultColor);
}
+
+ @SmallTest
+ public void testLstar() throws Exception {
+ int defaultColor = mResources.getColor(R.color.color_with_lstar);
+ assertEquals(mResources.getColor(R.color.testcolor3), defaultColor);
+ }
}
diff --git a/core/tests/coretests/src/android/provider/DeviceConfigTest.java b/core/tests/coretests/src/android/provider/DeviceConfigTest.java
index 61f58b0..fd39cde 100644
--- a/core/tests/coretests/src/android/provider/DeviceConfigTest.java
+++ b/core/tests/coretests/src/android/provider/DeviceConfigTest.java
@@ -762,6 +762,62 @@
// }
// }
+ @Test
+ public void syncDisabling() throws Exception {
+ Properties properties1 = new Properties.Builder(NAMESPACE)
+ .setString(KEY, VALUE)
+ .build();
+ Properties properties2 = new Properties.Builder(NAMESPACE)
+ .setString(KEY, VALUE2)
+ .build();
+
+ try {
+ // Ensure the device starts in a known state.
+ DeviceConfig.setSyncDisabled(Settings.Config.SYNC_DISABLED_MODE_NONE);
+
+ // Assert starting state.
+ assertThat(DeviceConfig.isSyncDisabled()).isFalse();
+ assertThat(DeviceConfig.setProperties(properties1)).isTrue();
+ assertThat(DeviceConfig.getProperties(NAMESPACE, KEY).getString(KEY, DEFAULT_VALUE))
+ .isEqualTo(VALUE);
+
+ // Test disabled (persistent). Persistence is not actually tested, that would require
+ // a host test.
+ DeviceConfig.setSyncDisabled(Settings.Config.SYNC_DISABLED_MODE_PERSISTENT);
+ assertThat(DeviceConfig.isSyncDisabled()).isTrue();
+ assertThat(DeviceConfig.setProperties(properties2)).isFalse();
+ assertThat(DeviceConfig.getProperties(NAMESPACE, KEY).getString(KEY, DEFAULT_VALUE))
+ .isEqualTo(VALUE);
+
+ // Return to not disabled.
+ DeviceConfig.setSyncDisabled(Settings.Config.SYNC_DISABLED_MODE_NONE);
+ assertThat(DeviceConfig.isSyncDisabled()).isFalse();
+ assertThat(DeviceConfig.setProperties(properties2)).isTrue();
+ assertThat(DeviceConfig.getProperties(NAMESPACE, KEY).getString(KEY, DEFAULT_VALUE))
+ .isEqualTo(VALUE2);
+
+ // Test disabled (persistent). Absence of persistence is not actually tested, that would
+ // require a host test.
+ DeviceConfig.setSyncDisabled(Settings.Config.SYNC_DISABLED_MODE_UNTIL_REBOOT);
+ assertThat(DeviceConfig.isSyncDisabled()).isTrue();
+ assertThat(DeviceConfig.setProperties(properties1)).isFalse();
+ assertThat(DeviceConfig.getProperties(NAMESPACE, KEY).getString(KEY, DEFAULT_VALUE))
+ .isEqualTo(VALUE2);
+
+ // Return to not disabled.
+ DeviceConfig.setSyncDisabled(Settings.Config.SYNC_DISABLED_MODE_NONE);
+ assertThat(DeviceConfig.isSyncDisabled()).isFalse();
+ assertThat(DeviceConfig.setProperties(properties1)).isTrue();
+ assertThat(DeviceConfig.getProperties(NAMESPACE, KEY).getString(KEY, DEFAULT_VALUE))
+ .isEqualTo(VALUE);
+ } finally {
+ // Try to return to the default sync disabled state in case of failure.
+ DeviceConfig.setSyncDisabled(Settings.Config.SYNC_DISABLED_MODE_NONE);
+
+ // NAMESPACE will be cleared by cleanUp()
+ }
+ }
+
private static boolean deleteViaContentProvider(String namespace, String key) {
ContentResolver resolver = InstrumentationRegistry.getContext().getContentResolver();
String compositeName = namespace + "/" + key;
diff --git a/core/tests/coretests/src/android/provider/NameValueCacheTest.java b/core/tests/coretests/src/android/provider/NameValueCacheTest.java
index 97e66c4..ee0b127 100644
--- a/core/tests/coretests/src/android/provider/NameValueCacheTest.java
+++ b/core/tests/coretests/src/android/provider/NameValueCacheTest.java
@@ -96,7 +96,8 @@
mCacheGenerationStore.set(0, ++mCurrentGeneration);
Bundle result = new Bundle();
- result.putBoolean(Settings.KEY_CONFIG_SET_RETURN, true);
+ result.putInt(Settings.KEY_CONFIG_SET_ALL_RETURN,
+ Settings.SET_ALL_RESULT_SUCCESS);
return result;
});
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryChargeCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryChargeCalculatorTest.java
index 23fc35d..6457e3f 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryChargeCalculatorTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryChargeCalculatorTest.java
@@ -35,11 +35,13 @@
private static final double PRECISION = 0.00001;
@Rule
- public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule()
- .setAveragePower(PowerProfile.POWER_BATTERY_CAPACITY, 1234.0); // Should be ignored
+ public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule();
@Test
public void testDischargeTotals() {
+ // Nominal battery capacity should be ignored
+ mStatsRule.setAveragePower(PowerProfile.POWER_BATTERY_CAPACITY, 1234.0);
+
final BatteryStatsImpl batteryStats = mStatsRule.getBatteryStats();
batteryStats.setBatteryStateLocked(BatteryManager.BATTERY_STATUS_DISCHARGING, 100,
@@ -56,7 +58,7 @@
BatteryUsageStats batteryUsageStats = mStatsRule.apply(calculator);
assertThat(batteryUsageStats.getConsumedPower())
- .isWithin(PRECISION).of(380.0);
+ .isWithin(PRECISION).of(1200.0); // 3,600 - 2,400
assertThat(batteryUsageStats.getDischargePercentage()).isEqualTo(10);
assertThat(batteryUsageStats.getDischargedPowerRange().getLower())
.isWithin(PRECISION).of(360.0);
@@ -74,4 +76,34 @@
assertThat(batteryUsageStats.getChargeTimeRemainingMs()).isEqualTo(100_000);
}
+
+ @Test
+ public void testDischargeTotals_chargeUahUnavailable() {
+ mStatsRule.setAveragePower(PowerProfile.POWER_BATTERY_CAPACITY, 4000.0);
+
+ final BatteryStatsImpl batteryStats = mStatsRule.getBatteryStats();
+
+ batteryStats.setBatteryStateLocked(BatteryManager.BATTERY_STATUS_DISCHARGING, 100,
+ /* plugType */ 0, 90, 72, 3700, 0, 0, 0,
+ 1_000_000, 1_000_000, 1_000_000);
+ batteryStats.setBatteryStateLocked(BatteryManager.BATTERY_STATUS_DISCHARGING, 100,
+ /* plugType */ 0, 85, 72, 3700, 0, 0, 0,
+ 1_500_000, 1_500_000, 1_500_000);
+ batteryStats.setBatteryStateLocked(BatteryManager.BATTERY_STATUS_DISCHARGING, 100,
+ /* plugType */ 0, 80, 72, 3700, 0, 0, 0,
+ 2_000_000, 2_000_000, 2_000_000);
+
+ BatteryChargeCalculator calculator = new BatteryChargeCalculator();
+ BatteryUsageStats batteryUsageStats = mStatsRule.apply(calculator);
+
+ assertThat(batteryUsageStats.getConsumedPower())
+ .isWithin(PRECISION).of(380.0); // 9.5% of 4,000.
+ assertThat(batteryUsageStats.getDischargePercentage()).isEqualTo(10);
+ assertThat(batteryUsageStats.getDischargedPowerRange().getLower())
+ .isWithin(PRECISION).of(360.0); // 9% of 4,000
+ assertThat(batteryUsageStats.getDischargedPowerRange().getUpper())
+ .isWithin(PRECISION).of(400.0); // 10% of 4,000
+ assertThat(batteryUsageStats.getBatteryTimeRemainingMs()).isEqualTo(8_000_000);
+ assertThat(batteryUsageStats.getChargeTimeRemainingMs()).isEqualTo(-1);
+ }
}
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsCpuTimesTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsCpuTimesTest.java
index 623e77e..54d8701 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsCpuTimesTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsCpuTimesTest.java
@@ -363,7 +363,6 @@
assertEquals("Unexpected system cpu time for uid=" + testUids[i],
uidTimesUs[i][1], u.getSystemCpuTimeUs(STATS_SINCE_CHARGED));
}
- verify(mCpuUidUserSysTimeReader).removeUid(isolatedUid);
// Add an isolated uid mapping and repeat the test.
@@ -453,7 +452,6 @@
}
assertNull("There shouldn't be an entry for invalid uid=" + invalidUid,
mBatteryStatsImpl.getUidStats().get(invalidUid));
- verify(mCpuUidUserSysTimeReader).removeUid(invalidUid);
}
@Test
@@ -943,7 +941,6 @@
assertNull("Unexpected screen-off cpu times for uid=" + testUids[i],
u.getScreenOffCpuFreqTimes(STATS_SINCE_CHARGED));
}
- verify(mCpuUidFreqTimeReader).removeUid(isolatedUid);
// Add an isolated uid mapping and repeat the test.
@@ -1038,7 +1035,6 @@
}
assertNull("There shouldn't be an entry for invalid uid=" + invalidUid,
mBatteryStatsImpl.getUidStats().get(invalidUid));
- verify(mCpuUidFreqTimeReader).removeUid(invalidUid);
}
@Test
@@ -1142,7 +1138,6 @@
}
assertNull("There shouldn't be an entry for invalid uid=" + invalidUid,
mBatteryStatsImpl.getUidStats().get(invalidUid));
- verify(mCpuUidActiveTimeReader).removeUid(invalidUid);
}
@Test
@@ -1259,7 +1254,6 @@
}
assertNull("There shouldn't be an entry for invalid uid=" + invalidUid,
mBatteryStatsImpl.getUidStats().get(invalidUid));
- verify(mCpuUidClusterTimeReader).removeUid(invalidUid);
}
@Test
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsProviderTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsProviderTest.java
index d36f06a..7f0449b 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsProviderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsProviderTest.java
@@ -45,7 +45,7 @@
private static final long MINUTE_IN_MS = 60 * 1000;
@Rule
- public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule();
+ public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule(12345);
@Test
public void test_getBatteryUsageStats() {
@@ -62,6 +62,8 @@
batteryStats.noteUidProcessStateLocked(APP_UID, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
40 * MINUTE_IN_MS, 40 * MINUTE_IN_MS);
+ mStatsRule.setCurrentTime(54321);
+
Context context = InstrumentationRegistry.getContext();
BatteryUsageStatsProvider provider = new BatteryUsageStatsProvider(context, batteryStats);
@@ -75,6 +77,9 @@
.isEqualTo(20 * MINUTE_IN_MS);
assertThat(uidBatteryConsumer.getTimeInStateMs(UidBatteryConsumer.STATE_BACKGROUND))
.isEqualTo(10 * MINUTE_IN_MS);
+
+ assertThat(batteryUsageStats.getStatsStartTimestamp()).isEqualTo(12345);
+ assertThat(batteryUsageStats.getStatsEndTimestamp()).isEqualTo(54321);
}
@Test
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsRule.java b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsRule.java
index 8c9591c..961e859 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsRule.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsRule.java
@@ -57,8 +57,13 @@
private boolean mScreenOn;
public BatteryUsageStatsRule() {
+ this(0);
+ }
+
+ public BatteryUsageStatsRule(long currentTime) {
Context context = InstrumentationRegistry.getContext();
mPowerProfile = spy(new PowerProfile(context, true /* forTest */));
+ mMockClocks.currentTime = currentTime;
mBatteryStats = new MockBatteryStatsImpl(mMockClocks);
mBatteryStats.setPowerProfile(mPowerProfile);
}
@@ -164,6 +169,10 @@
mMockClocks.uptime = uptimeMs;
}
+ public void setCurrentTime(long currentTimeMs) {
+ mMockClocks.currentTime = currentTimeMs;
+ }
+
BatteryUsageStats apply(PowerCalculator... calculators) {
return apply(new BatteryUsageStatsQuery.Builder().includePowerModels().build(),
calculators);
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsTest.java
index c8564ac..380b4ae 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsTest.java
@@ -44,13 +44,13 @@
@Test
public void testBuilder() {
- BatteryUsageStats batteryUsageStats = buildBatteryUsageStats();
+ BatteryUsageStats batteryUsageStats = buildBatteryUsageStats().build();
validateBatteryUsageStats(batteryUsageStats);
}
@Test
public void testParcelability() {
- final BatteryUsageStats outBatteryUsageStats = buildBatteryUsageStats();
+ final BatteryUsageStats outBatteryUsageStats = buildBatteryUsageStats().build();
final Parcel outParcel = Parcel.obtain();
outParcel.writeParcelable(outBatteryUsageStats, 0);
final byte[] bytes = outParcel.marshall();
@@ -65,9 +65,17 @@
validateBatteryUsageStats(inBatteryUsageStats);
}
+
+ @Test
+ public void testDefaultSessionDuration() {
+ final BatteryUsageStats stats =
+ buildBatteryUsageStats().setStatsDuration(10000).build();
+ assertThat(stats.getStatsDuration()).isEqualTo(10000);
+ }
+
@Test
public void testDump() {
- final BatteryUsageStats stats = buildBatteryUsageStats();
+ final BatteryUsageStats stats = buildBatteryUsageStats().build();
final StringWriter out = new StringWriter();
try (PrintWriter pw = new PrintWriter(out)) {
stats.dump(pw, " ");
@@ -93,7 +101,7 @@
assertThat(allNames).hasSize(BatteryConsumer.POWER_COMPONENT_COUNT);
}
- private BatteryUsageStats buildBatteryUsageStats() {
+ private BatteryUsageStats.Builder buildBatteryUsageStats() {
final MockClocks clocks = new MockClocks();
final MockBatteryStatsImpl batteryStats = new MockBatteryStatsImpl(clocks);
final BatteryStatsImpl.Uid batteryStatsUid = batteryStats.getUidStatsLocked(2000);
@@ -103,7 +111,8 @@
.setBatteryCapacity(4000)
.setDischargePercentage(20)
.setDischargedPowerRange(1000, 2000)
- .setStatsStartTimestamp(1000);
+ .setStatsStartTimestamp(1000)
+ .setStatsEndTimestamp(3000);
builder.getOrCreateUidBatteryConsumerBuilder(batteryStatsUid)
.setPackageWithHighestDrain("foo")
.setTimeInStateMs(UidBatteryConsumer.STATE_FOREGROUND, 1000)
@@ -152,7 +161,7 @@
.setUsageDurationForCustomComponentMillis(
BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID, 40);
- return builder.build();
+ return builder;
}
public void validateBatteryUsageStats(BatteryUsageStats batteryUsageStats) {
@@ -162,6 +171,8 @@
assertThat(batteryUsageStats.getDischargedPowerRange().getLower()).isEqualTo(1000);
assertThat(batteryUsageStats.getDischargedPowerRange().getUpper()).isEqualTo(2000);
assertThat(batteryUsageStats.getStatsStartTimestamp()).isEqualTo(1000);
+ assertThat(batteryUsageStats.getStatsEndTimestamp()).isEqualTo(3000);
+ assertThat(batteryUsageStats.getStatsDuration()).isEqualTo(2000);
final List<UidBatteryConsumer> uidBatteryConsumers =
batteryUsageStats.getUidBatteryConsumers();
diff --git a/core/tests/coretests/src/com/android/internal/os/MockClocks.java b/core/tests/coretests/src/com/android/internal/os/MockClocks.java
index d0fa756..c26505e 100644
--- a/core/tests/coretests/src/com/android/internal/os/MockClocks.java
+++ b/core/tests/coretests/src/com/android/internal/os/MockClocks.java
@@ -21,6 +21,8 @@
public long realtime;
/** Uptime in ms */
public long uptime;
+ /** Current time in ms */
+ public long currentTime;
@Override
public long elapsedRealtime() {
@@ -31,4 +33,9 @@
public long uptimeMillis() {
return uptime;
}
+
+ @Override
+ public long currentTimeMillis() {
+ return currentTime;
+ }
}
diff --git a/data/etc/Android.bp b/data/etc/Android.bp
index 85b60f8..be1e2b2 100644
--- a/data/etc/Android.bp
+++ b/data/etc/Android.bp
@@ -127,6 +127,20 @@
}
prebuilt_etc {
+ name: "privapp_whitelist_com.android.networkstack",
+ sub_dir: "permissions",
+ src: "com.android.networkstack.xml",
+ filename_from_src: true,
+}
+
+prebuilt_etc {
+ name: "privapp_whitelist_com.android.networkstack.tethering",
+ sub_dir: "permissions",
+ src: "com.android.networkstack.tethering.xml",
+ filename_from_src: true,
+}
+
+prebuilt_etc {
name: "privapp_whitelist_com.android.provision",
system_ext_specific: true,
sub_dir: "permissions",
diff --git a/data/etc/car/com.android.car.bugreport.xml b/data/etc/car/com.android.car.bugreport.xml
index 2ff9835..ec9128e 100644
--- a/data/etc/car/com.android.car.bugreport.xml
+++ b/data/etc/car/com.android.car.bugreport.xml
@@ -22,5 +22,6 @@
<permission name="android.permission.MANAGE_USERS"/>
<permission name="android.permission.BROADCAST_CLOSE_SYSTEM_DIALOGS"/>
<permission name="android.car.permission.CAR_DRIVING_STATE"/>
+ <permission name="android.car.permission.CONTROL_CAR_CLIMATE"/>
</privapp-permissions>
</permissions>
diff --git a/data/etc/com.android.networkstack.tethering.xml b/data/etc/com.android.networkstack.tethering.xml
new file mode 100644
index 0000000..f26a961
--- /dev/null
+++ b/data/etc/com.android.networkstack.tethering.xml
@@ -0,0 +1,28 @@
+<?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
+-->
+
+<permissions>
+ <privapp-permissions package="com.android.networkstack.tethering">
+ <permission name="android.permission.BLUETOOTH_PRIVILEGED" />
+ <permission name="android.permission.MANAGE_USB"/>
+ <permission name="android.permission.MODIFY_PHONE_STATE"/>
+ <permission name="android.permission.READ_NETWORK_USAGE_HISTORY"/>
+ <permission name="android.permission.TETHER_PRIVILEGED"/>
+ <permission name="android.permission.UPDATE_APP_OPS_STATS"/>
+ <permission name="android.permission.UPDATE_DEVICE_STATS"/>
+ </privapp-permissions>
+</permissions>
diff --git a/data/etc/com.android.networkstack.xml b/data/etc/com.android.networkstack.xml
new file mode 100644
index 0000000..06fec1c
--- /dev/null
+++ b/data/etc/com.android.networkstack.xml
@@ -0,0 +1,38 @@
+<?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
+-->
+
+<permissions>
+ <privapp-permissions package="com.android.networkstack">
+ <permission name="android.permission.ACCESS_NETWORK_CONDITIONS"/>
+ <permission name="android.permission.CONNECTIVITY_INTERNAL"/>
+ <permission name="android.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS"/>
+ <permission name="android.permission.CONTROL_VPN"/>
+ <permission name="android.permission.INTERACT_ACROSS_USERS"/>
+ <permission name="android.permission.LOCAL_MAC_ADDRESS"/>
+ <permission name="android.permission.MANAGE_SUBSCRIPTION_PLANS"/>
+ <permission name="android.permission.MANAGE_USB"/>
+ <permission name="android.permission.NETWORK_BYPASS_PRIVATE_DNS"/>
+ <permission name="android.permission.PACKET_KEEPALIVE_OFFLOAD"/>
+ <permission name="android.permission.READ_NETWORK_USAGE_HISTORY"/>
+ <permission name="android.permission.READ_PRECISE_PHONE_STATE"/>
+ <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
+ <permission name="android.permission.READ_WIFI_CREDENTIAL"/>
+ <permission name="android.permission.RECEIVE_DATA_ACTIVITY_CHANGE"/>
+ <permission name="android.permission.TETHER_PRIVILEGED"/>
+ <permission name="android.permission.WRITE_SECURE_SETTINGS"/>
+ </privapp-permissions>
+</permissions>
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 545a564..19332c7 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -154,9 +154,6 @@
<permission name="android.permission.CHANGE_COMPONENT_ENABLED_STATE" />
<permission name="android.permission.MODIFY_AUDIO_ROUTING" />
<permission name="android.permission.GET_RUNTIME_PERMISSION_GROUP_MAPPING" />
-
- <!-- For permission hub 2 debugging only -->
- <permission name="android.permission.GET_ACCOUNTS_PRIVILEGED"/>
</privapp-permissions>
<privapp-permissions package="com.android.phone">
@@ -271,36 +268,6 @@
<permission name="android.permission.READ_COMPAT_CHANGE_CONFIG" />
</privapp-permissions>
- <privapp-permissions package="com.android.networkstack">
- <permission name="android.permission.ACCESS_NETWORK_CONDITIONS"/>
- <permission name="android.permission.CONNECTIVITY_INTERNAL"/>
- <permission name="android.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS"/>
- <permission name="android.permission.CONTROL_VPN"/>
- <permission name="android.permission.INTERACT_ACROSS_USERS"/>
- <permission name="android.permission.LOCAL_MAC_ADDRESS"/>
- <permission name="android.permission.MANAGE_SUBSCRIPTION_PLANS"/>
- <permission name="android.permission.MANAGE_USB"/>
- <permission name="android.permission.NETWORK_BYPASS_PRIVATE_DNS"/>
- <permission name="android.permission.PACKET_KEEPALIVE_OFFLOAD"/>
- <permission name="android.permission.READ_NETWORK_USAGE_HISTORY"/>
- <permission name="android.permission.READ_PRECISE_PHONE_STATE"/>
- <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
- <permission name="android.permission.READ_WIFI_CREDENTIAL"/>
- <permission name="android.permission.RECEIVE_DATA_ACTIVITY_CHANGE"/>
- <permission name="android.permission.TETHER_PRIVILEGED"/>
- <permission name="android.permission.WRITE_SECURE_SETTINGS"/>
- </privapp-permissions>
-
- <privapp-permissions package="com.android.networkstack.tethering">
- <permission name="android.permission.BLUETOOTH_PRIVILEGED" />
- <permission name="android.permission.MANAGE_USB"/>
- <permission name="android.permission.MODIFY_PHONE_STATE"/>
- <permission name="android.permission.READ_NETWORK_USAGE_HISTORY"/>
- <permission name="android.permission.TETHER_PRIVILEGED"/>
- <permission name="android.permission.UPDATE_APP_OPS_STATS"/>
- <permission name="android.permission.UPDATE_DEVICE_STATS"/>
- </privapp-permissions>
-
<privapp-permissions package="com.android.server.telecom">
<permission name="android.permission.BIND_CONNECTION_SERVICE"/>
<permission name="android.permission.BIND_INCALL_SERVICE"/>
@@ -470,6 +437,7 @@
<permission name="android.permission.MANAGE_DEBUGGING" />
<!-- Permissions required for CTS test - TimeManagerTest -->
<permission name="android.permission.MANAGE_TIME_AND_ZONE_DETECTION" />
+ <permission name="android.permission.SUGGEST_EXTERNAL_TIME" />
<!-- Permissions required for CTS test - android.server.biometrics -->
<permission name="android.permission.USE_BIOMETRIC" />
<permission name="android.permission.TEST_BIOMETRIC" />
diff --git a/graphics/java/android/graphics/HardwareRenderer.java b/graphics/java/android/graphics/HardwareRenderer.java
index 8f1223b..954d062 100644
--- a/graphics/java/android/graphics/HardwareRenderer.java
+++ b/graphics/java/android/graphics/HardwareRenderer.java
@@ -1195,6 +1195,7 @@
// so not checking for isolated process here.
initHintSession();
+ nSetIsHighEndGfx(ActivityManager.isHighEndGfx());
// Defensively clear out the context in case we were passed a context that can leak
// if we live longer than it, e.g. an activity context.
mContext = null;
@@ -1315,6 +1316,8 @@
private static native void nSetSdrWhitePoint(long nativeProxy, float whitePoint);
+ private static native void nSetIsHighEndGfx(boolean isHighEndGfx);
+
private static native int nSyncAndDrawFrame(long nativeProxy, long[] frameInfo, int size);
private static native void nDestroy(long nativeProxy, long rootRenderNode);
diff --git a/graphics/java/android/graphics/RadialGradient.java b/graphics/java/android/graphics/RadialGradient.java
index 199365e..e582e66 100644
--- a/graphics/java/android/graphics/RadialGradient.java
+++ b/graphics/java/android/graphics/RadialGradient.java
@@ -122,14 +122,18 @@
* between the center and edge of the circle.
* @param tileMode The Shader tiling mode
*
- * @throws IllegalArgumentException If one of the following circumstances:
- * - There are less than two colors
- * - The colors do not share the same {@link ColorSpace}
- * - The colors do not use a valid {@link ColorSpace}
- * - The {@code stops} parameter is not {@code null} and has a different length
- * from {@code colors}.
- * - The {@param startRadius} is negative
- * - The {@param endRadius} is less than or equal to zero
+ * @throws IllegalArgumentException In one of the following circumstances:
+ * <ul>
+ * <li>There are less than two colors</li>
+ * <li>The colors do not share the same {@link ColorSpace}</li>
+ * <li>The colors do not use a valid {@link ColorSpace}</li>
+ * <li>
+ * The {@code stops} parameter is not {@code null} and has a different length from
+ * {@code colors}.
+ * </li>
+ * <li>The {@code startRadius} is negative</li>
+ * <li>The {@code endRadius} is less than or equal to zero</li>
+ * </ul>
*/
public RadialGradient(float startX, float startY, @FloatRange(from = 0.0f) float startRadius,
float endX, float endY, @FloatRange(from = 0.0f, fromInclusive = false) float endRadius,
diff --git a/graphics/java/android/graphics/drawable/RippleShader.java b/graphics/java/android/graphics/drawable/RippleShader.java
index 6c0981a..e5651e0 100644
--- a/graphics/java/android/graphics/drawable/RippleShader.java
+++ b/graphics/java/android/graphics/drawable/RippleShader.java
@@ -50,15 +50,17 @@
+ "}"
+ "const float PI = 3.1415926535897932384626;\n"
+ "\n"
+ + "float threshold(float v, float l, float h) {\n"
+ + " return step(l, v) * (1.0 - step(h, v));\n"
+ + "}\n"
+ "float sparkles(vec2 uv, float t) {\n"
+ " float n = triangleNoise(uv);\n"
+ " float s = 0.0;\n"
+ " for (float i = 0; i < 4; i += 1) {\n"
- + " float l = i * 0.01;\n"
- + " float h = l + 0.2;\n"
- + " float o = smoothstep(n - l, h, n);\n"
- + " o *= abs(sin(PI * o * (t + 0.55 * i)));\n"
- + " s += o;\n"
+ + " float l = i * 0.1;\n"
+ + " float h = l + 0.025;\n"
+ + " float o = sin(PI * (t + 0.35 * i));\n"
+ + " s += threshold(n + o, l, h);\n"
+ " }\n"
+ " return saturate(s) * in_sparkleColor.a;\n"
+ "}\n"
@@ -125,9 +127,6 @@
private static final double PI_ROTATE_RIGHT = Math.PI * 0.0078125;
private static final double PI_ROTATE_LEFT = Math.PI * -0.0078125;
- private float mNoisePhase;
- private float mProgress;
-
RippleShader() {
super(SHADER, false);
}
@@ -143,15 +142,6 @@
setUniform("in_maxRadius", radius);
}
- /**
- * Continuous offset used as noise phase.
- */
- public void setNoisePhase(float phase) {
- mNoisePhase = phase;
- setUniform("in_noisePhase", phase);
- updateTurbulence();
- }
-
public void setOrigin(float x, float y) {
setUniform("in_origin", new float[] {x, y});
}
@@ -161,18 +151,20 @@
}
public void setProgress(float progress) {
- mProgress = progress;
setUniform("in_progress", progress);
- updateTurbulence();
}
- private void updateTurbulence() {
- final float turbulencePhase = (float) ((mProgress + mNoisePhase * 0.333f) * 5f * Math.PI);
- setUniform("in_turbulencePhase", turbulencePhase);
+ /**
+ * Continuous offset used as noise phase.
+ */
+ public void setNoisePhase(float phase) {
+ setUniform("in_noisePhase", phase * 0.001f);
//
// Keep in sync with: frameworks/base/libs/hwui/pipeline/skia/AnimatedDrawables.h
//
+ final float turbulencePhase = phase;
+ setUniform("in_turbulencePhase", turbulencePhase);
final float scale = 1.5f;
setUniform("in_tCircle1", new float[]{
(float) (scale * 0.5 + (turbulencePhase * 0.01 * Math.cos(scale * 0.55))),
diff --git a/graphics/java/android/graphics/fonts/SystemFonts.java b/graphics/java/android/graphics/fonts/SystemFonts.java
index 255f9e6..0da2b51 100644
--- a/graphics/java/android/graphics/fonts/SystemFonts.java
+++ b/graphics/java/android/graphics/fonts/SystemFonts.java
@@ -85,6 +85,15 @@
}
}
+ /**
+ * @hide
+ */
+ public static void resetAvailableFonts() {
+ synchronized (LOCK) {
+ sAvailableFonts = null;
+ }
+ }
+
private static @Nullable ByteBuffer mmap(@NonNull String fullPath) {
try (FileInputStream file = new FileInputStream(fullPath)) {
final FileChannel fileChannel = file.getChannel();
@@ -262,8 +271,14 @@
*/
@VisibleForTesting
public static Map<String, FontFamily[]> buildSystemFallback(FontConfig fontConfig) {
+ return buildSystemFallback(fontConfig, new ArrayMap<>());
+ }
+
+ /** @hide */
+ @VisibleForTesting
+ public static Map<String, FontFamily[]> buildSystemFallback(FontConfig fontConfig,
+ ArrayMap<String, ByteBuffer> outBufferCache) {
final Map<String, FontFamily[]> fallbackMap = new ArrayMap<>();
- final ArrayMap<String, ByteBuffer> bufferCache = new ArrayMap<>();
final List<FontConfig.FontFamily> xmlFamilies = fontConfig.getFontFamilies();
final ArrayMap<String, ArrayList<FontFamily>> fallbackListMap = new ArrayMap<>();
@@ -273,7 +288,7 @@
if (familyName == null) {
continue;
}
- appendNamedFamily(xmlFamily, bufferCache, fallbackListMap);
+ appendNamedFamily(xmlFamily, outBufferCache, fallbackListMap);
}
// Then, add fallback fonts to the each fallback map.
@@ -282,7 +297,7 @@
// The first family (usually the sans-serif family) is always placed immediately
// after the primary family in the fallback.
if (i == 0 || xmlFamily.getName() == null) {
- pushFamilyToFallback(xmlFamily, fallbackListMap, bufferCache);
+ pushFamilyToFallback(xmlFamily, fallbackListMap, outBufferCache);
}
}
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreSecretKeyFactorySpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreSecretKeyFactorySpi.java
index fe05989..97592b4 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreSecretKeyFactorySpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreSecretKeyFactorySpi.java
@@ -252,7 +252,9 @@
blockModes,
userAuthenticationRequired,
(int) userAuthenticationValidityDurationSeconds,
- keymasterHwEnforcedUserAuthenticators,
+ userAuthenticationRequirementEnforcedBySecureHardware
+ ? keymasterHwEnforcedUserAuthenticators
+ : keymasterSwEnforcedUserAuthenticators,
userAuthenticationRequirementEnforcedBySecureHardware,
userAuthenticationValidWhileOnBody,
trustedUserPresenceRequired,
diff --git a/libs/WindowManager/Shell/AndroidManifest.xml b/libs/WindowManager/Shell/AndroidManifest.xml
index 6bd0e0a..10df726 100644
--- a/libs/WindowManager/Shell/AndroidManifest.xml
+++ b/libs/WindowManager/Shell/AndroidManifest.xml
@@ -18,6 +18,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.wm.shell">
<!-- System permission required by WM Shell Task Organizer. -->
+ <uses-permission android:name="android.permission.CAPTURE_BLACKOUT_CONTENT" />
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
<uses-permission android:name="android.permission.ROTATE_SURFACE_FLINGER" />
<uses-permission android:name="android.permission.READ_FRAME_BUFFER" />
diff --git a/libs/WindowManager/Shell/res/drawable/bubble_stack_user_education_bg.xml b/libs/WindowManager/Shell/res/drawable/bubble_stack_user_education_bg.xml
index 4b9219c..dcc7821 100644
--- a/libs/WindowManager/Shell/res/drawable/bubble_stack_user_education_bg.xml
+++ b/libs/WindowManager/Shell/res/drawable/bubble_stack_user_education_bg.xml
@@ -14,9 +14,10 @@
~ limitations under the License.
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle">
- <solid android:color="?android:attr/colorAccent"/>
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ android:shape="rectangle">
<corners
android:bottomRightRadius="360dp"
android:topRightRadius="360dp" />
+ <solid android:color="?androidprv:attr/colorAccentPrimary" />
</shape>
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/drawable/bubble_stack_user_education_bg_rtl.xml b/libs/WindowManager/Shell/res/drawable/bubble_stack_user_education_bg_rtl.xml
index c7baba1..70b63e6 100644
--- a/libs/WindowManager/Shell/res/drawable/bubble_stack_user_education_bg_rtl.xml
+++ b/libs/WindowManager/Shell/res/drawable/bubble_stack_user_education_bg_rtl.xml
@@ -14,9 +14,10 @@
~ 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/colorAccent"/>
<corners
android:bottomLeftRadius="360dp"
android:topLeftRadius="360dp" />
+ <solid android:color="?androidprv:attr/colorAccentPrimary" />
</shape>
diff --git a/libs/WindowManager/Shell/res/layout/bubble_expanded_view.xml b/libs/WindowManager/Shell/res/layout/bubble_expanded_view.xml
index 81656fe..33e009e 100644
--- a/libs/WindowManager/Shell/res/layout/bubble_expanded_view.xml
+++ b/libs/WindowManager/Shell/res/layout/bubble_expanded_view.xml
@@ -35,6 +35,7 @@
android:layout_height="wrap_content"
android:focusable="true"
android:text="@string/manage_bubbles_text"
+ android:textSize="@*android:dimen/text_size_body_2_material"
android:textColor="?android:attr/textColorPrimary"
/>
diff --git a/libs/WindowManager/Shell/res/layout/bubble_overflow_container.xml b/libs/WindowManager/Shell/res/layout/bubble_overflow_container.xml
index 270186a..76fe3c9 100644
--- a/libs/WindowManager/Shell/res/layout/bubble_overflow_container.xml
+++ b/libs/WindowManager/Shell/res/layout/bubble_overflow_container.xml
@@ -55,6 +55,7 @@
android:text="@string/bubble_overflow_empty_title"
android:fontFamily="@*android:string/config_bodyFontFamilyMedium"
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Body2"
+ android:textSize="@*android:dimen/text_size_body_2_material"
android:textColor="?android:attr/textColorSecondary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -66,6 +67,7 @@
android:layout_height="wrap_content"
android:fontFamily="@*android:string/config_bodyFontFamily"
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Body2"
+ android:textSize="@*android:dimen/text_size_body_2_material"
android:textColor="?android:attr/textColorSecondary"
android:text="@string/bubble_overflow_empty_subtitle"
android:paddingBottom="@dimen/bubble_empty_overflow_subtitle_padding"
diff --git a/libs/WindowManager/Shell/res/layout/bubble_stack_user_education.xml b/libs/WindowManager/Shell/res/layout/bubble_stack_user_education.xml
index fe6a8bd..fd4c3ba 100644
--- a/libs/WindowManager/Shell/res/layout/bubble_stack_user_education.xml
+++ b/libs/WindowManager/Shell/res/layout/bubble_stack_user_education.xml
@@ -38,7 +38,7 @@
android:gravity="start"
android:textAlignment="viewStart"
android:text="@string/bubbles_user_education_title"
- android:textColor="?android:attr/textColorPrimaryInverse"
+ android:textColor="@android:color/system_neutral1_900"
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Headline"/>
<TextView
@@ -49,7 +49,7 @@
android:gravity="start"
android:textAlignment="viewStart"
android:text="@string/bubbles_user_education_description"
- android:textColor="?android:attr/textColorPrimaryInverse"
+ android:textColor="@android:color/system_neutral1_900"
android:fontFamily="@*android:string/config_bodyFontFamily"
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Body2"/>
</LinearLayout>
diff --git a/libs/WindowManager/Shell/res/layout/bubbles_manage_button_education.xml b/libs/WindowManager/Shell/res/layout/bubbles_manage_button_education.xml
index 3d48e40..c5c42fc 100644
--- a/libs/WindowManager/Shell/res/layout/bubbles_manage_button_education.xml
+++ b/libs/WindowManager/Shell/res/layout/bubbles_manage_button_education.xml
@@ -41,7 +41,7 @@
android:ellipsize="end"
android:gravity="start"
android:textAlignment="viewStart"
- android:textColor="?android:attr/textColorPrimaryInverse"
+ android:textColor="@android:color/system_neutral1_900"
android:text="@string/bubbles_user_education_manage_title"
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Headline"/>
@@ -56,7 +56,7 @@
android:ellipsize="end"
android:gravity="start"
android:textAlignment="viewStart"
- android:textColor="?android:attr/textColorPrimaryInverse"
+ android:textColor="@android:color/system_neutral1_900"
android:fontFamily="@*android:string/config_bodyFontFamily"
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Body2"/>
@@ -75,7 +75,7 @@
android:focusable="true"
android:clickable="false"
android:text="@string/manage_bubbles_text"
- android:textColor="?android:attr/textColorPrimaryInverse"
+ android:textColor="@android:color/system_neutral1_900"
/>
<com.android.wm.shell.common.AlphaOptimizedButton
@@ -86,7 +86,7 @@
android:layout_height="wrap_content"
android:focusable="true"
android:text="@string/bubbles_user_education_got_it"
- android:textColor="?android:attr/textColorPrimaryInverse"
+ android:textColor="@android:color/system_neutral1_900"
/>
</LinearLayout>
</LinearLayout>
diff --git a/libs/WindowManager/Shell/res/values/config.xml b/libs/WindowManager/Shell/res/values/config.xml
index 26f98d8..4c2863e 100644
--- a/libs/WindowManager/Shell/res/values/config.xml
+++ b/libs/WindowManager/Shell/res/values/config.xml
@@ -24,6 +24,9 @@
<!-- Animation duration for resizing of PIP. -->
<integer name="config_pipResizeAnimationDuration">425</integer>
+ <!-- Animation duration for crossfading of PIP (specifically to fade out the layer on top). -->
+ <integer name="config_pipCrossfadeAnimationDuration">150</integer>
+
<!-- Allow dragging the PIP to a location to close it -->
<bool name="config_pipEnableDismissDragToEdge">true</bool>
diff --git a/libs/WindowManager/Shell/res/values/dimen.xml b/libs/WindowManager/Shell/res/values/dimen.xml
index d94030d..9b1beb3 100644
--- a/libs/WindowManager/Shell/res/values/dimen.xml
+++ b/libs/WindowManager/Shell/res/values/dimen.xml
@@ -97,7 +97,7 @@
<!-- How much the bubble flyout text container is elevated. -->
<dimen name="bubble_flyout_elevation">4dp</dimen>
<!-- How much padding is around the left and right sides of the flyout text. -->
- <dimen name="bubble_flyout_padding_x">12dp</dimen>
+ <dimen name="bubble_flyout_padding_x">14dp</dimen>
<!-- How much padding is around the top and bottom of the flyout text. -->
<dimen name="bubble_flyout_padding_y">10dp</dimen>
<!-- Size of the triangle that points from the flyout to the bubble stack. -->
diff --git a/libs/WindowManager/Shell/res/values/ids.xml b/libs/WindowManager/Shell/res/values/ids.xml
index 434a000..8831b61 100644
--- a/libs/WindowManager/Shell/res/values/ids.xml
+++ b/libs/WindowManager/Shell/res/values/ids.xml
@@ -16,6 +16,8 @@
-->
<resources>
<item type="id" name="action_pip_resize" />
+ <item type="id" name="action_pip_stash" />
+ <item type="id" name="action_pip_unstash" />
<!-- Accessibility actions for the docked stack divider -->
<item type="id" name="action_move_tl_full" />
diff --git a/libs/WindowManager/Shell/res/values/strings.xml b/libs/WindowManager/Shell/res/values/strings.xml
index b1425e4..e512698 100644
--- a/libs/WindowManager/Shell/res/values/strings.xml
+++ b/libs/WindowManager/Shell/res/values/strings.xml
@@ -48,6 +48,12 @@
<!-- Accessibility action for resizing PIP [CHAR LIMIT=NONE] -->
<string name="accessibility_action_pip_resize">Resize</string>
+ <!-- Accessibility action for stashing PIP [CHAR LIMIT=NONE] -->
+ <string name="accessibility_action_pip_stash">Stash</string>
+
+ <!-- Accessibility action for unstashing PIP [CHAR LIMIT=NONE] -->
+ <string name="accessibility_action_pip_unstash">Unstash</string>
+
<!-- TODO Deprecated. Label for PIP action to Minimize the PIP. DO NOT TRANSLATE [CHAR LIMIT=25] -->
<string name="pip_phone_minimize">Minimize</string>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/FullscreenTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/FullscreenTaskListener.java
index 6984ea45..006730d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/FullscreenTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/FullscreenTaskListener.java
@@ -42,7 +42,7 @@
private final SyncTransactionQueue mSyncQueue;
- private final SparseArray<SurfaceControl> mLeashByTaskId = new SparseArray<>();
+ private final SparseArray<TaskData> mDataByTaskId = new SparseArray<>();
public FullscreenTaskListener(SyncTransactionQueue syncQueue) {
mSyncQueue = syncQueue;
@@ -50,14 +50,14 @@
@Override
public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash) {
- if (mLeashByTaskId.get(taskInfo.taskId) != null) {
+ if (mDataByTaskId.get(taskInfo.taskId) != null) {
throw new IllegalStateException("Task appeared more than once: #" + taskInfo.taskId);
}
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Fullscreen Task Appeared: #%d",
taskInfo.taskId);
- mLeashByTaskId.put(taskInfo.taskId, leash);
- if (Transitions.ENABLE_SHELL_TRANSITIONS) return;
final Point positionInParent = taskInfo.positionInParent;
+ mDataByTaskId.put(taskInfo.taskId, new TaskData(leash, positionInParent));
+ if (Transitions.ENABLE_SHELL_TRANSITIONS) return;
mSyncQueue.runInSync(t -> {
// Reset several properties back to fullscreen (PiP, for example, leaves all these
// properties in a bad state).
@@ -72,45 +72,57 @@
@Override
public void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo) {
if (Transitions.ENABLE_SHELL_TRANSITIONS) return;
- final SurfaceControl leash = mLeashByTaskId.get(taskInfo.taskId);
+ final TaskData data = mDataByTaskId.get(taskInfo.taskId);
final Point positionInParent = taskInfo.positionInParent;
- mSyncQueue.runInSync(t -> {
- // Reset several properties back. For instance, when an Activity enters PiP with
- // multiple activities in the same task, a new task will be created from that Activity
- // and we want reset the leash of the original task.
- t.setPosition(leash, positionInParent.x, positionInParent.y);
- t.setWindowCrop(leash, null);
- });
+ if (!positionInParent.equals(data.positionInParent)) {
+ data.positionInParent.set(positionInParent.x, positionInParent.y);
+ mSyncQueue.runInSync(t -> {
+ t.setPosition(data.surface, positionInParent.x, positionInParent.y);
+ });
+ }
}
@Override
public void onTaskVanished(ActivityManager.RunningTaskInfo taskInfo) {
- if (mLeashByTaskId.get(taskInfo.taskId) == null) {
+ if (mDataByTaskId.get(taskInfo.taskId) == null) {
Slog.e(TAG, "Task already vanished: #" + taskInfo.taskId);
return;
}
- mLeashByTaskId.remove(taskInfo.taskId);
+ mDataByTaskId.remove(taskInfo.taskId);
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Fullscreen Task Vanished: #%d",
taskInfo.taskId);
}
@Override
public void attachChildSurfaceToTask(int taskId, SurfaceControl.Builder b) {
- if (!mLeashByTaskId.contains(taskId)) {
+ if (!mDataByTaskId.contains(taskId)) {
throw new IllegalArgumentException("There is no surface for taskId=" + taskId);
}
- b.setParent(mLeashByTaskId.get(taskId));
+ b.setParent(mDataByTaskId.get(taskId).surface);
}
@Override
public void dump(@NonNull PrintWriter pw, String prefix) {
final String innerPrefix = prefix + " ";
pw.println(prefix + this);
- pw.println(innerPrefix + mLeashByTaskId.size() + " Tasks");
+ pw.println(innerPrefix + mDataByTaskId.size() + " Tasks");
}
@Override
public String toString() {
return TAG + ":" + taskListenerTypeToString(TASK_LISTENER_TYPE_FULLSCREEN);
}
+
+ /**
+ * Per-task data for each managed task.
+ */
+ private static class TaskData {
+ public final SurfaceControl surface;
+ public final Point positionInParent;
+
+ public TaskData(SurfaceControl surface, Point positionInParent) {
+ this.surface = surface;
+ this.positionInParent = positionInParent;
+ }
+ }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandlerImpl.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandlerImpl.java
index d451f4a..0b941b5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandlerImpl.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandlerImpl.java
@@ -16,14 +16,14 @@
package com.android.wm.shell;
-import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_POSITION_BOTTOM_OR_RIGHT;
+import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_BOTTOM_OR_RIGHT;
import com.android.wm.shell.apppairs.AppPairsController;
import com.android.wm.shell.common.ShellExecutor;
-import com.android.wm.shell.pip.Pip;
import com.android.wm.shell.hidedisplaycutout.HideDisplayCutoutController;
import com.android.wm.shell.legacysplitscreen.LegacySplitScreenController;
import com.android.wm.shell.onehanded.OneHandedController;
+import com.android.wm.shell.pip.Pip;
import com.android.wm.shell.splitscreen.SplitScreenController;
import java.io.PrintWriter;
@@ -145,7 +145,7 @@
}
final int taskId = new Integer(args[2]);
final int sideStagePosition = args.length > 3
- ? new Integer(args[3]) : STAGE_POSITION_BOTTOM_OR_RIGHT;
+ ? new Integer(args[3]) : SPLIT_POSITION_BOTTOM_OR_RIGHT;
mSplitScreenOptional.ifPresent(split -> split.moveToSideStage(taskId, sideStagePosition));
return true;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java b/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java
index eb82c6d..e6d088e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java
@@ -20,11 +20,15 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_BOTTOM_OR_RIGHT;
+import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_TOP_OR_LEFT;
+import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_UNDEFINED;
import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_TASK_ORG;
import android.app.ActivityManager;
import android.graphics.Rect;
import android.view.SurfaceControl;
+import android.view.SurfaceSession;
import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
@@ -35,6 +39,7 @@
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayImeController;
+import com.android.wm.shell.common.SurfaceUtils;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.common.split.SplitLayout;
@@ -45,7 +50,7 @@
* {@link #mTaskInfo1} and {@link #mTaskInfo2} in the pair.
* Also includes all UI for managing the pair like the divider.
*/
-class AppPair implements ShellTaskOrganizer.TaskListener, SplitLayout.LayoutChangeListener {
+class AppPair implements ShellTaskOrganizer.TaskListener, SplitLayout.SplitLayoutHandler {
private static final String TAG = AppPair.class.getSimpleName();
private ActivityManager.RunningTaskInfo mRootTaskInfo;
@@ -54,6 +59,9 @@
private SurfaceControl mTaskLeash1;
private ActivityManager.RunningTaskInfo mTaskInfo2;
private SurfaceControl mTaskLeash2;
+ private SurfaceControl mDimLayer1;
+ private SurfaceControl mDimLayer2;
+ private final SurfaceSession mSurfaceSession = new SurfaceSession();
private final AppPairsController mController;
private final SyncTransactionQueue mSyncQueue;
@@ -101,7 +109,8 @@
mSplitLayout = new SplitLayout(TAG + "SplitDivider",
mDisplayController.getDisplayContext(mRootTaskInfo.displayId),
mRootTaskInfo.configuration, this /* layoutChangeListener */,
- b -> b.setParent(mRootTaskLeash), mDisplayImeController);
+ b -> b.setParent(mRootTaskLeash), mDisplayImeController,
+ mController.getTaskOrganizer());
final WindowContainerToken token1 = task1.token;
final WindowContainerToken token2 = task2.token;
@@ -153,9 +162,13 @@
} else if (taskInfo.taskId == getTaskId1()) {
mTaskInfo1 = taskInfo;
mTaskLeash1 = leash;
+ mSyncQueue.runInSync(t -> mDimLayer1 =
+ SurfaceUtils.makeDimLayer(t, mTaskLeash1, "Dim layer", mSurfaceSession));
} else if (taskInfo.taskId == getTaskId2()) {
mTaskInfo2 = taskInfo;
mTaskLeash2 = leash;
+ mSyncQueue.runInSync(t -> mDimLayer2 =
+ SurfaceUtils.makeDimLayer(t, mTaskLeash2, "Dim layer", mSurfaceSession));
} else {
throw new IllegalStateException("Unknown task=" + taskInfo.taskId);
}
@@ -182,6 +195,11 @@
@Override
public void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo) {
+ if (!taskInfo.supportsMultiWindow) {
+ // Dismiss AppPair if the task no longer supports multi window.
+ mController.unpair(mRootTaskInfo.taskId);
+ return;
+ }
if (taskInfo.taskId == getRootTaskId()) {
if (mRootTaskInfo.isVisible != taskInfo.isVisible) {
mSyncQueue.runInSync(t -> {
@@ -208,12 +226,31 @@
}
@Override
+ public int getSplitItemPosition(WindowContainerToken token) {
+ if (token == null) {
+ return SPLIT_POSITION_UNDEFINED;
+ }
+
+ if (token.equals(mTaskInfo1.getToken())) {
+ return SPLIT_POSITION_TOP_OR_LEFT;
+ } else if (token.equals(mTaskInfo2.getToken())) {
+ return SPLIT_POSITION_BOTTOM_OR_RIGHT;
+ }
+
+ return SPLIT_POSITION_UNDEFINED;
+ }
+
+ @Override
public void onTaskVanished(ActivityManager.RunningTaskInfo taskInfo) {
if (taskInfo.taskId == getRootTaskId()) {
// We don't want to release this object back to the pool since the root task went away.
mController.unpair(mRootTaskInfo.taskId, false /* releaseToPool */);
- } else if (taskInfo.taskId == getTaskId1() || taskInfo.taskId == getTaskId2()) {
+ } else if (taskInfo.taskId == getTaskId1()) {
mController.unpair(mRootTaskInfo.taskId);
+ mSyncQueue.runInSync(t -> t.remove(mDimLayer1));
+ } else if (taskInfo.taskId == getTaskId2()) {
+ mController.unpair(mRootTaskInfo.taskId);
+ mSyncQueue.runInSync(t -> t.remove(mDimLayer2));
}
}
@@ -259,40 +296,16 @@
@Override
public void onBoundsChanging(SplitLayout layout) {
- final SurfaceControl dividerLeash = mSplitLayout.getDividerLeash();
- if (dividerLeash == null) return;
- final Rect dividerBounds = layout.getDividerBounds();
- final Rect bounds1 = layout.getBounds1();
- final Rect bounds2 = layout.getBounds2();
- mSyncQueue.runInSync(t -> t
- .setPosition(dividerLeash, dividerBounds.left, dividerBounds.top)
- .setPosition(mTaskLeash1, bounds1.left, bounds1.top)
- .setPosition(mTaskLeash2, bounds2.left, bounds2.top)
- // Sets crop to prevent visible region of tasks overlap with each other when
- // re-positioning surfaces while resizing.
- .setWindowCrop(mTaskLeash1, bounds1.width(), bounds1.height())
- .setWindowCrop(mTaskLeash2, bounds2.width(), bounds2.height()));
+ mSyncQueue.runInSync(t ->
+ layout.applySurfaceChanges(t, mTaskLeash1, mTaskLeash2, mDimLayer1, mDimLayer2));
}
@Override
public void onBoundsChanged(SplitLayout layout) {
- final SurfaceControl dividerLeash = mSplitLayout.getDividerLeash();
- if (dividerLeash == null) return;
- final Rect dividerBounds = layout.getDividerBounds();
- final Rect bounds1 = layout.getBounds1();
- final Rect bounds2 = layout.getBounds2();
final WindowContainerTransaction wct = new WindowContainerTransaction();
- wct.setBounds(mTaskInfo1.token, bounds1)
- .setBounds(mTaskInfo2.token, bounds2);
- mController.getTaskOrganizer().applyTransaction(wct);
- mSyncQueue.runInSync(t -> t
- // Resets layer of divider bar to make sure it is always on top.
- .setLayer(dividerLeash, Integer.MAX_VALUE)
- .setPosition(dividerLeash, dividerBounds.left, dividerBounds.top)
- .setPosition(mTaskLeash1, bounds1.left, bounds1.top)
- .setPosition(mTaskLeash2, bounds2.left, bounds2.top)
- // Resets crop to apply new surface bounds directly.
- .setWindowCrop(mTaskLeash1, null)
- .setWindowCrop(mTaskLeash2, null));
+ layout.applyTaskChanges(wct, mTaskInfo1, mTaskInfo2);
+ mSyncQueue.queue(wct);
+ mSyncQueue.runInSync(t ->
+ layout.applySurfaceChanges(t, mTaskLeash1, mTaskLeash2, mDimLayer1, mDimLayer2));
}
}
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 6a0f061..7dcedfe 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
@@ -715,7 +715,7 @@
}
if (newConfig.fontScale != mFontScale) {
mFontScale = newConfig.fontScale;
- mStackView.updateFontScale(mFontScale);
+ mStackView.updateFontScale();
}
if (newConfig.getLayoutDirection() != mLayoutDirection) {
mLayoutDirection = newConfig.getLayoutDirection();
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 d8ec650..a87da88 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
@@ -46,6 +46,7 @@
import android.os.RemoteException;
import android.util.AttributeSet;
import android.util.Log;
+import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.SurfaceControl;
import android.view.View;
@@ -250,26 +251,14 @@
protected void onFinishInflate() {
super.onFinishInflate();
- Resources res = getResources();
+ mSettingsIcon = findViewById(R.id.settings_button);
+ mSettingsIconHeight = getContext().getResources().getDimensionPixelSize(
+ R.dimen.bubble_manage_button_height);
mPointerView = findViewById(R.id.pointer_view);
- mPointerWidth = res.getDimensionPixelSize(R.dimen.bubble_pointer_width);
- mPointerHeight = res.getDimensionPixelSize(R.dimen.bubble_pointer_height);
-
- mTopPointer = new ShapeDrawable(TriangleShape.create(
- mPointerWidth, mPointerHeight, true /* pointUp */));
- mLeftPointer = new ShapeDrawable(TriangleShape.createHorizontal(
- mPointerWidth, mPointerHeight, true /* pointLeft */));
- mRightPointer = new ShapeDrawable(TriangleShape.createHorizontal(
- mPointerWidth, mPointerHeight, false /* pointLeft */));
-
mCurrentPointer = mTopPointer;
mPointerView.setVisibility(INVISIBLE);
- mSettingsIconHeight = getContext().getResources().getDimensionPixelSize(
- R.dimen.bubble_manage_button_height);
- mSettingsIcon = findViewById(R.id.settings_button);
-
- // Set ActivityView's alpha value as zero, since there is no view content to be shown.
+ // Set TaskView's alpha value as zero, since there is no view content to be shown.
setContentVisibility(false);
mExpandedViewContainer.setOutlineProvider(new ViewOutlineProvider() {
@@ -293,7 +282,6 @@
applyThemeAttrs();
- mExpandedViewPadding = res.getDimensionPixelSize(R.dimen.bubble_expanded_view_padding);
setClipToPadding(false);
setOnTouchListener((view, motionEvent) -> {
if (mTaskView == null) {
@@ -354,7 +342,41 @@
Resources res = getResources();
mMinHeight = res.getDimensionPixelSize(R.dimen.bubble_expanded_default_height);
mOverflowHeight = res.getDimensionPixelSize(R.dimen.bubble_overflow_height);
+ mExpandedViewPadding = res.getDimensionPixelSize(R.dimen.bubble_expanded_view_padding);
+
mPointerMargin = res.getDimensionPixelSize(R.dimen.bubble_pointer_margin);
+ mPointerWidth = res.getDimensionPixelSize(R.dimen.bubble_pointer_width);
+ mPointerHeight = res.getDimensionPixelSize(R.dimen.bubble_pointer_height);
+
+ mTopPointer = new ShapeDrawable(TriangleShape.create(
+ mPointerWidth, mPointerHeight, true /* pointUp */));
+ mLeftPointer = new ShapeDrawable(TriangleShape.createHorizontal(
+ mPointerWidth, mPointerHeight, true /* pointLeft */));
+ mRightPointer = new ShapeDrawable(TriangleShape.createHorizontal(
+ mPointerWidth, mPointerHeight, false /* pointLeft */));
+
+ final float fontSize = mContext.getResources()
+ .getDimensionPixelSize(com.android.internal.R.dimen.text_size_body_2_material);
+ if (mSettingsIcon != null) {
+ mSettingsIcon.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize);
+ }
+ if (mOverflowView != null) {
+ mOverflowView.updateFontSize();
+ }
+ if (mPointerView != null) {
+ updatePointerView();
+ }
+ }
+
+ void updateFontSize() {
+ final float fontSize = mContext.getResources()
+ .getDimensionPixelSize(com.android.internal.R.dimen.text_size_body_2_material);
+ if (mSettingsIcon != null) {
+ mSettingsIcon.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize);
+ }
+ if (mOverflowView != null) {
+ mOverflowView.updateFontSize();
+ }
}
void applyThemeAttrs() {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleFlyoutView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleFlyoutView.java
index 57a2b6c..79f77d7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleFlyoutView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleFlyoutView.java
@@ -65,6 +65,9 @@
private static final long FLYOUT_FADE_OUT_DURATION = 150L;
private static final long FLYOUT_FADE_IN_DURATION = 250L;
+ // Whether the flyout view should show a pointer to the bubble.
+ private static final boolean SHOW_POINTER = false;
+
private final int mFlyoutPadding;
private final int mFlyoutSpaceFromBubble;
private final int mPointerSize;
@@ -166,14 +169,16 @@
final Resources res = getResources();
mFlyoutPadding = res.getDimensionPixelSize(R.dimen.bubble_flyout_padding_x);
mFlyoutSpaceFromBubble = res.getDimensionPixelSize(R.dimen.bubble_flyout_space_from_bubble);
- mPointerSize = res.getDimensionPixelSize(R.dimen.bubble_flyout_pointer_size);
+ mPointerSize = SHOW_POINTER
+ ? res.getDimensionPixelSize(R.dimen.bubble_flyout_pointer_size)
+ : 0;
mBubbleElevation = res.getDimensionPixelSize(R.dimen.bubble_elevation);
mFlyoutElevation = res.getDimensionPixelSize(R.dimen.bubble_flyout_elevation);
final TypedArray ta = mContext.obtainStyledAttributes(
new int[] {
- android.R.attr.colorBackgroundFloating,
+ com.android.internal.R.attr.colorSurface,
android.R.attr.dialogCornerRadius});
mFloatingBackgroundColor = ta.getColor(0, Color.WHITE);
mCornerRadius = ta.getDimensionPixelSize(1, 0);
@@ -182,7 +187,7 @@
// Add padding for the pointer on either side, onDraw will draw it in this space.
setPadding(mPointerSize, 0, mPointerSize, 0);
setWillNotDraw(false);
- setClipChildren(false);
+ setClipChildren(!SHOW_POINTER);
setTranslationZ(mFlyoutElevation);
setOutlineProvider(new ViewOutlineProvider() {
@Override
@@ -216,12 +221,11 @@
super.onDraw(canvas);
}
- void updateFontSize(float fontScale) {
+ void updateFontSize() {
final float fontSize = mContext.getResources()
.getDimensionPixelSize(com.android.internal.R.dimen.text_size_body_2_material);
- final float newFontSize = fontSize * fontScale;
- mMessageText.setTextSize(TypedValue.COMPLEX_UNIT_PX, newFontSize);
- mSenderText.setTextSize(TypedValue.COMPLEX_UNIT_PX, newFontSize);
+ mMessageText.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize);
+ mSenderText.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize);
}
/*
@@ -462,6 +466,7 @@
/** Renders the 'pointer' triangle that points from the flyout to the bubble stack. */
private void renderPointerTriangle(
Canvas canvas, float currentFlyoutWidth, float currentFlyoutHeight) {
+ if (!SHOW_POINTER) return;
canvas.save();
// Translation to apply for the 'retraction' effect as the flyout collapses.
@@ -489,13 +494,12 @@
// current position.
relevantTriangle.getOutline(mTriangleOutline);
mTriangleOutline.offset((int) arrowTranslationX, (int) arrowTranslationY);
-
canvas.restore();
}
/** Builds an outline that includes the transformed flyout background and triangle. */
private void getOutline(Outline outline) {
- if (!mTriangleOutline.isEmpty()) {
+ if (!mTriangleOutline.isEmpty() || !SHOW_POINTER) {
// Draw the rect into the outline as a path so we can merge the triangle path into it.
final Path rectPath = new Path();
final float interpolatedRadius = getInterpolatedRadius();
@@ -504,7 +508,7 @@
outline.setPath(rectPath);
// Get rid of the triangle path once it has disappeared behind the flyout.
- if (mPercentStillFlyout > 0.5f) {
+ if (SHOW_POINTER && mPercentStillFlyout > 0.5f) {
outline.mPath.addPath(mTriangleOutline.mPath);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflow.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflow.kt
index 36908b8..e4b1f64 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflow.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflow.kt
@@ -82,7 +82,7 @@
fun updateResources() {
bitmapSize = positioner.bubbleBitmapSize
- iconBitmapSize = (bitmapSize * 0.46f).toInt()
+ iconBitmapSize = (bitmapSize * ICON_BITMAP_SIZE_PERCENT).toInt()
val bubbleSize = positioner.bubbleSize
overflowBtn?.layoutParams = FrameLayout.LayoutParams(bubbleSize, bubbleSize)
expandedView?.updateDimensions()
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflowContainerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflowContainerView.java
index af5b3a6..d3b7ae2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflowContainerView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflowContainerView.java
@@ -27,6 +27,7 @@
import android.graphics.Color;
import android.util.AttributeSet;
import android.util.Log;
+import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -181,6 +182,13 @@
mEmptyStateSubtitle.setTextColor(textColor);
}
+ public void updateFontSize() {
+ final float fontSize = mContext.getResources()
+ .getDimensionPixelSize(com.android.internal.R.dimen.text_size_body_2_material);
+ mEmptyStateTitle.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize);
+ mEmptyStateSubtitle.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize);
+ }
+
private final BubbleData.Listener mDataListener = new BubbleData.Listener() {
@Override
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 07d16b5..64a3b8f 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
@@ -1180,8 +1180,17 @@
addView(mFlyout, new FrameLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT));
}
- void updateFontScale(float fontScale) {
- mFlyout.updateFontSize(fontScale);
+ void updateFontScale() {
+ setUpManageMenu();
+ mFlyout.updateFontSize();
+ for (Bubble b : mBubbleData.getBubbles()) {
+ if (b.getExpandedView() != null) {
+ b.getExpandedView().updateFontSize();
+ }
+ }
+ if (mBubbleOverflow != null) {
+ mBubbleOverflow.getExpandedView().updateFontSize();
+ }
}
private void updateOverflow() {
@@ -1244,6 +1253,8 @@
/** Respond to the display size change by recalculating view size and location. */
public void onDisplaySizeChanged() {
updateOverflow();
+ setUpManageMenu();
+ setUpFlyout();
mBubbleSize = mPositioner.getBubbleSize();
for (Bubble b : mBubbleData.getBubbles()) {
if (b.getIconView() == null) {
@@ -1251,6 +1262,9 @@
continue;
}
b.getIconView().setLayoutParams(new LayoutParams(mBubbleSize, mBubbleSize));
+ if (b.getExpandedView() != null) {
+ b.getExpandedView().updateDimensions();
+ }
}
mBubbleOverflow.getIconView().setLayoutParams(new LayoutParams(mBubbleSize, mBubbleSize));
mExpandedAnimationController.updateResources();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/ScreenshotUtils.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/ScreenshotUtils.java
new file mode 100644
index 0000000..e59845c
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/ScreenshotUtils.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.common;
+
+import android.graphics.GraphicBuffer;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.view.SurfaceControl;
+
+/**
+ * Helpers for working with screenshots.
+ */
+public class ScreenshotUtils {
+
+ /**
+ * Take a screenshot of the specified SurfaceControl.
+ *
+ * @param t the transaction used to set changes on the resulting screenshot.
+ * @param sc the SurfaceControl to take a screenshot of
+ * @param crop the crop to use when capturing the screenshot
+ *
+ * @return A SurfaceControl where the screenshot will be attached, or null if failed.
+ */
+ public static SurfaceControl takeScreenshot(SurfaceControl.Transaction t, SurfaceControl sc,
+ Rect crop) {
+ final SurfaceControl.ScreenshotHardwareBuffer buffer = SurfaceControl.captureLayers(
+ new SurfaceControl.LayerCaptureArgs.Builder(sc)
+ .setSourceCrop(crop)
+ .setCaptureSecureLayers(true)
+ .setAllowProtected(true)
+ .build()
+ );
+ if (buffer == null || buffer.getHardwareBuffer() == null) {
+ return null;
+ }
+ final GraphicBuffer graphicBuffer = GraphicBuffer.createFromHardwareBuffer(
+ buffer.getHardwareBuffer());
+ final SurfaceControl screenshot = new SurfaceControl.Builder()
+ .setName("ScreenshotUtils screenshot")
+ .setFormat(PixelFormat.TRANSLUCENT)
+ .setSecure(buffer.containsSecureLayers())
+ .setCallsite("ScreenshotUtils.takeScreenshot")
+ .setBLASTLayer()
+ .build();
+
+ t.setBuffer(screenshot, graphicBuffer);
+ t.setColorSpace(screenshot, buffer.getColorSpace());
+ t.reparent(screenshot, sc);
+ t.setLayer(screenshot, Integer.MAX_VALUE);
+ t.show(screenshot);
+ t.apply();
+ return screenshot;
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SurfaceUtils.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SurfaceUtils.java
new file mode 100644
index 0000000..55c5125
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SurfaceUtils.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.common;
+
+import android.view.SurfaceControl;
+import android.view.SurfaceSession;
+
+/**
+ * Helpers for handling surface.
+ */
+public class SurfaceUtils {
+ /** Creates a dim layer above indicated host surface. */
+ public static SurfaceControl makeDimLayer(SurfaceControl.Transaction t, SurfaceControl host,
+ String name, SurfaceSession surfaceSession) {
+ SurfaceControl dimLayer = new SurfaceControl.Builder(surfaceSession)
+ .setParent(host)
+ .setColorLayer()
+ .setName(name)
+ .setCallsite("SurfaceUtils.makeDimLayer")
+ .build();
+ t.setLayer(dimLayer, Integer.MAX_VALUE).setColor(dimLayer, new float[]{0f, 0f, 0f});
+ return dimLayer;
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
index 442e7a4..cba019a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
@@ -36,13 +36,11 @@
import com.android.internal.policy.DividerSnapAlgorithm;
import com.android.wm.shell.R;
import com.android.wm.shell.animation.Interpolators;
-import com.android.wm.shell.common.DisplayImeController;
/**
* Divider for multi window splits.
*/
-public class DividerView extends FrameLayout implements View.OnTouchListener,
- DisplayImeController.ImePositionProcessor {
+public class DividerView extends FrameLayout implements View.OnTouchListener {
public static final long TOUCH_ANIMATION_DURATION = 150;
public static final long TOUCH_RELEASE_ANIMATION_DURATION = 200;
@@ -99,12 +97,6 @@
}
@Override
- public void onImeVisibilityChanged(int displayId, boolean isShowing) {
- if (displayId != getDisplay().getDisplayId()) return;
- setInteractive(!isShowing);
- }
-
- @Override
public boolean onTouch(View v, MotionEvent event) {
if (mSplitLayout == null || !mInteractive) {
return false;
@@ -139,11 +131,10 @@
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
- mVelocityTracker.addMovement(event);
releaseTouching();
-
if (!mMoving) break;
+ mVelocityTracker.addMovement(event);
mVelocityTracker.computeCurrentVelocity(1000 /* units */);
final float velocity = isLandscape
? mVelocityTracker.getXVelocity()
@@ -217,7 +208,7 @@
mViewHost.relayout(lp);
}
- private void setInteractive(boolean interactive) {
+ void setInteractive(boolean interactive) {
if (interactive == mInteractive) return;
mInteractive = interactive;
releaseTouching();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
index d318a5a..e42f511 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
@@ -25,16 +25,22 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
+import android.annotation.IntDef;
+import android.app.ActivityManager;
import android.content.Context;
import android.content.res.Configuration;
+import android.content.res.Resources;
import android.graphics.Rect;
import android.view.SurfaceControl;
import android.view.WindowInsets;
import android.view.WindowManager;
+import android.window.WindowContainerToken;
+import android.window.WindowContainerTransaction;
import androidx.annotation.Nullable;
import com.android.internal.policy.DividerSnapAlgorithm;
+import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.animation.Interpolators;
import com.android.wm.shell.common.DisplayImeController;
@@ -42,7 +48,32 @@
* Records and handles layout of splits. Helps to calculate proper bounds when configuration or
* divide position changes.
*/
-public class SplitLayout {
+public final class SplitLayout {
+ /**
+ * Split position isn't specified normally meaning to use what ever it is currently set to.
+ */
+ public static final int SPLIT_POSITION_UNDEFINED = -1;
+
+ /**
+ * Specifies that a split is positioned at the top half of the screen if
+ * in portrait mode or at the left half of the screen if in landscape mode.
+ */
+ public static final int SPLIT_POSITION_TOP_OR_LEFT = 0;
+
+ /**
+ * Specifies that a split is positioned at the bottom half of the screen if
+ * in portrait mode or at the right half of the screen if in landscape mode.
+ */
+ public static final int SPLIT_POSITION_BOTTOM_OR_RIGHT = 1;
+
+ @IntDef(prefix = {"SPLIT_POSITION_"}, value = {
+ SPLIT_POSITION_UNDEFINED,
+ SPLIT_POSITION_TOP_OR_LEFT,
+ SPLIT_POSITION_BOTTOM_OR_RIGHT
+ })
+ public @interface SplitPosition {
+ }
+
private final int mDividerWindowWidth;
private final int mDividerInsets;
private final int mDividerSize;
@@ -51,8 +82,11 @@
private final Rect mDividerBounds = new Rect();
private final Rect mBounds1 = new Rect();
private final Rect mBounds2 = new Rect();
- private final LayoutChangeListener mLayoutChangeListener;
+ private final SplitLayoutHandler mSplitLayoutHandler;
private final SplitWindowManager mSplitWindowManager;
+ private final DisplayImeController mDisplayImeController;
+ private final ImePositionProcessor mImePositionProcessor;
+ private final ShellTaskOrganizer mTaskOrganizer;
private Context mContext;
private DividerSnapAlgorithm mDividerSnapAlgorithm;
@@ -60,18 +94,21 @@
private boolean mInitialized = false;
public SplitLayout(String windowName, Context context, Configuration configuration,
- LayoutChangeListener layoutChangeListener,
+ SplitLayoutHandler splitLayoutHandler,
SplitWindowManager.ParentContainerCallbacks parentContainerCallbacks,
- DisplayImeController displayImeController) {
+ DisplayImeController displayImeController, ShellTaskOrganizer taskOrganizer) {
mContext = context.createConfigurationContext(configuration);
- mLayoutChangeListener = layoutChangeListener;
+ mSplitLayoutHandler = splitLayoutHandler;
+ mDisplayImeController = displayImeController;
mSplitWindowManager = new SplitWindowManager(
- windowName, mContext, configuration, parentContainerCallbacks,
- displayImeController);
+ windowName, mContext, configuration, parentContainerCallbacks);
+ mTaskOrganizer = taskOrganizer;
+ mImePositionProcessor = new ImePositionProcessor(mContext.getDisplayId());
- mDividerWindowWidth = context.getResources().getDimensionPixelSize(
+ final Resources resources = context.getResources();
+ mDividerWindowWidth = resources.getDimensionPixelSize(
com.android.internal.R.dimen.docked_stack_divider_thickness);
- mDividerInsets = context.getResources().getDimensionPixelSize(
+ mDividerInsets = resources.getDimensionPixelSize(
com.android.internal.R.dimen.docked_stack_divider_insets);
mDividerSize = mDividerWindowWidth - mDividerInsets * 2;
@@ -82,17 +119,17 @@
/** Gets bounds of the primary split. */
public Rect getBounds1() {
- return mBounds1;
+ return new Rect(mBounds1);
}
/** Gets bounds of the secondary split. */
public Rect getBounds2() {
- return mBounds2;
+ return new Rect(mBounds2);
}
/** Gets bounds of divider window. */
public Rect getDividerBounds() {
- return mDividerBounds;
+ return new Rect(mDividerBounds);
}
/** Returns leash of the current divider bar. */
@@ -153,6 +190,7 @@
if (mInitialized) return;
mInitialized = true;
mSplitWindowManager.init(this);
+ mDisplayImeController.addPositionProcessor(mImePositionProcessor);
}
/** Releases the surface holding the current {@link DividerView}. */
@@ -160,6 +198,8 @@
if (!mInitialized) return;
mInitialized = false;
mSplitWindowManager.release();
+ mDisplayImeController.removePositionProcessor(mImePositionProcessor);
+ mImePositionProcessor.reset();
}
/**
@@ -168,14 +208,14 @@
*/
void updateDivideBounds(int position) {
updateBounds(position);
- mLayoutChangeListener.onBoundsChanging(this);
mSplitWindowManager.setResizingSplits(true);
+ mSplitLayoutHandler.onBoundsChanging(this);
}
void setDividePosition(int position) {
mDividePosition = position;
updateBounds(mDividePosition);
- mLayoutChangeListener.onBoundsChanged(this);
+ mSplitLayoutHandler.onBoundsChanged(this);
mSplitWindowManager.setResizingSplits(false);
}
@@ -192,11 +232,11 @@
public void snapToTarget(int currentPosition, DividerSnapAlgorithm.SnapTarget snapTarget) {
switch (snapTarget.flag) {
case FLAG_DISMISS_START:
- mLayoutChangeListener.onSnappedToDismiss(false /* bottomOrRight */);
+ mSplitLayoutHandler.onSnappedToDismiss(false /* bottomOrRight */);
mSplitWindowManager.setResizingSplits(false);
break;
case FLAG_DISMISS_END:
- mLayoutChangeListener.onSnappedToDismiss(true /* bottomOrRight */);
+ mSplitLayoutHandler.onSnappedToDismiss(true /* bottomOrRight */);
mSplitWindowManager.setResizingSplits(false);
break;
default:
@@ -206,7 +246,7 @@
}
void onDoubleTappedDivider() {
- mLayoutChangeListener.onDoubleTappedDivider();
+ mSplitLayoutHandler.onDoubleTappedDivider();
}
/**
@@ -265,8 +305,38 @@
return bounds.width() > bounds.height();
}
- /** Listens layout change event. */
- public interface LayoutChangeListener {
+ /** Apply recorded surface layout to the {@link SurfaceControl.Transaction}. */
+ public void applySurfaceChanges(SurfaceControl.Transaction t, SurfaceControl leash1,
+ SurfaceControl leash2, SurfaceControl dimLayer1, SurfaceControl dimLayer2) {
+ final Rect dividerBounds = mImePositionProcessor.adjustForIme(mDividerBounds);
+ final Rect bounds1 = mImePositionProcessor.adjustForIme(mBounds1);
+ final Rect bounds2 = mImePositionProcessor.adjustForIme(mBounds2);
+ final SurfaceControl dividerLeash = getDividerLeash();
+ if (dividerLeash != null) {
+ t.setPosition(dividerLeash, dividerBounds.left, dividerBounds.top)
+ // Resets layer of divider bar to make sure it is always on top.
+ .setLayer(dividerLeash, Integer.MAX_VALUE);
+ }
+
+ t.setPosition(leash1, bounds1.left, bounds1.top)
+ .setWindowCrop(leash1, bounds1.width(), bounds1.height());
+
+ t.setPosition(leash2, bounds2.left, bounds2.top)
+ .setWindowCrop(leash2, bounds2.width(), bounds2.height());
+
+ mImePositionProcessor.applySurfaceDimValues(t, dimLayer1, dimLayer2);
+ }
+
+ /** Apply recorded task layout to the {@link WindowContainerTransaction}. */
+ public void applyTaskChanges(WindowContainerTransaction wct,
+ ActivityManager.RunningTaskInfo task1, ActivityManager.RunningTaskInfo task2) {
+ wct.setBounds(task1.token, mImePositionProcessor.adjustForIme(mBounds1))
+ .setBounds(task2.token, mImePositionProcessor.adjustForIme(mBounds2));
+ }
+
+ /** Handles layout change event. */
+ public interface SplitLayoutHandler {
+
/** Calls when dismissing split. */
void onSnappedToDismiss(boolean snappedToEnd);
@@ -279,5 +349,133 @@
/** Calls when user double tapped on the divider bar. */
default void onDoubleTappedDivider() {
}
+
+ /** Returns split position of the token. */
+ @SplitPosition
+ int getSplitItemPosition(WindowContainerToken token);
+ }
+
+ /** Records IME top offset changes and updates SplitLayout correspondingly. */
+ private class ImePositionProcessor implements DisplayImeController.ImePositionProcessor {
+ /**
+ * Maximum size of an adjusted split bounds relative to original stack bounds. Used to
+ * restrict IME adjustment so that a min portion of top split remains visible.
+ */
+ private static final float ADJUSTED_SPLIT_FRACTION_MAX = 0.7f;
+ private static final float ADJUSTED_NONFOCUS_DIM = 0.3f;
+
+ private final int mDisplayId;
+
+ private int mYOffsetForIme;
+ private float mDimValue1;
+ private float mDimValue2;
+
+ private int mStartImeTop;
+ private int mEndImeTop;
+
+ private int mTargetYOffset;
+ private int mLastYOffset;
+ private float mTargetDim1;
+ private float mTargetDim2;
+ private float mLastDim1;
+ private float mLastDim2;
+
+ private ImePositionProcessor(int displayId) {
+ mDisplayId = displayId;
+ }
+
+ @Override
+ public int onImeStartPositioning(int displayId, int hiddenTop, int shownTop,
+ boolean showing, boolean isFloating, SurfaceControl.Transaction t) {
+ if (displayId != mDisplayId) return 0;
+ final int imeTargetPosition = getImeTargetPosition();
+ if (!mInitialized || imeTargetPosition == SPLIT_POSITION_UNDEFINED) return 0;
+ mStartImeTop = showing ? hiddenTop : shownTop;
+ mEndImeTop = showing ? shownTop : hiddenTop;
+
+ // Update target dim values
+ mLastDim1 = mDimValue1;
+ mTargetDim1 = imeTargetPosition == SPLIT_POSITION_BOTTOM_OR_RIGHT && showing
+ ? ADJUSTED_NONFOCUS_DIM : 0.0f;
+ mLastDim2 = mDimValue2;
+ mTargetDim2 = imeTargetPosition == SPLIT_POSITION_TOP_OR_LEFT && showing
+ ? ADJUSTED_NONFOCUS_DIM : 0.0f;
+
+ // Calculate target bounds offset for IME
+ mLastYOffset = mYOffsetForIme;
+ final boolean needOffset = imeTargetPosition == SPLIT_POSITION_BOTTOM_OR_RIGHT
+ && !isFloating && !isLandscape(mRootBounds) && showing;
+ mTargetYOffset = needOffset ? getTargetYOffset() : 0;
+
+ // Make {@link DividerView} non-interactive while IME showing in split mode. Listen to
+ // ImePositionProcessor#onImeVisibilityChanged directly in DividerView is not enough
+ // because DividerView won't receive onImeVisibilityChanged callback after it being
+ // re-inflated.
+ mSplitWindowManager.setInteractive(
+ !showing || imeTargetPosition == SPLIT_POSITION_UNDEFINED);
+
+ return 0;
+ }
+
+ @Override
+ public void onImePositionChanged(int displayId, int imeTop, SurfaceControl.Transaction t) {
+ if (displayId != mDisplayId) return;
+ onProgress(getProgress(imeTop));
+ mSplitLayoutHandler.onBoundsChanging(SplitLayout.this);
+ }
+
+ @Override
+ public void onImeEndPositioning(int displayId, boolean cancel,
+ SurfaceControl.Transaction t) {
+ if (displayId != mDisplayId || cancel) return;
+ onProgress(1.0f);
+ mSplitLayoutHandler.onBoundsChanging(SplitLayout.this);
+ }
+
+ private int getTargetYOffset() {
+ final int desireOffset = Math.abs(mEndImeTop - mStartImeTop);
+ // Make sure to keep at least 30% visible for the top split.
+ final int maxOffset = (int) (mBounds1.height() * ADJUSTED_SPLIT_FRACTION_MAX);
+ return -Math.min(desireOffset, maxOffset);
+ }
+
+ @SplitPosition
+ private int getImeTargetPosition() {
+ final WindowContainerToken token = mTaskOrganizer.getImeTarget(mDisplayId);
+ return mSplitLayoutHandler.getSplitItemPosition(token);
+ }
+
+ private float getProgress(int currImeTop) {
+ return ((float) currImeTop - mStartImeTop) / (mEndImeTop - mStartImeTop);
+ }
+
+ private void onProgress(float progress) {
+ mDimValue1 = getProgressValue(mLastDim1, mTargetDim1, progress);
+ mDimValue2 = getProgressValue(mLastDim2, mTargetDim2, progress);
+ mYOffsetForIme =
+ (int) getProgressValue((float) mLastYOffset, (float) mTargetYOffset, progress);
+ }
+
+ private float getProgressValue(float start, float end, float progress) {
+ return start + (end - start) * progress;
+ }
+
+ private void reset() {
+ mYOffsetForIme = 0;
+ mDimValue1 = mDimValue2 = 0.0f;
+ }
+
+ /* Adjust bounds with IME offset. */
+ private Rect adjustForIme(Rect bounds) {
+ final Rect temp = new Rect(bounds);
+ if (mYOffsetForIme != 0) temp.offset(0, mYOffsetForIme);
+ return temp;
+ }
+
+ private void applySurfaceDimValues(SurfaceControl.Transaction t, SurfaceControl dimLayer1,
+ SurfaceControl dimLayer2) {
+ t.setAlpha(dimLayer1, mDimValue1).setVisibility(dimLayer1, mDimValue1 > 0.001f);
+ t.setAlpha(dimLayer2, mDimValue2).setVisibility(dimLayer2, mDimValue2 > 0.001f);
+ }
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
index f6efb01..0cea0ef 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
@@ -46,7 +46,6 @@
import androidx.annotation.Nullable;
import com.android.wm.shell.R;
-import com.android.wm.shell.common.DisplayImeController;
/**
* Holds view hierarchy of a root surface and helps to inflate {@link DividerView} for a split.
@@ -55,7 +54,6 @@
private static final String TAG = SplitWindowManager.class.getSimpleName();
private final String mWindowName;
- private final DisplayImeController mDisplayImeController;
private final ParentContainerCallbacks mParentContainerCallbacks;
private Context mContext;
private SurfaceControlViewHost mViewHost;
@@ -68,13 +66,11 @@
}
public SplitWindowManager(String windowName, Context context, Configuration config,
- ParentContainerCallbacks parentContainerCallbacks,
- DisplayImeController displayImeController) {
+ ParentContainerCallbacks parentContainerCallbacks) {
super(config, null /* rootSurface */, null /* hostInputToken */);
mContext = context.createConfigurationContext(config);
mParentContainerCallbacks = parentContainerCallbacks;
mWindowName = windowName;
- mDisplayImeController = displayImeController;
}
@Override
@@ -128,7 +124,6 @@
lp.privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION | PRIVATE_FLAG_TRUSTED_OVERLAY;
mViewHost.setView(mDividerView, lp);
mDividerView.setup(splitLayout, mViewHost);
- mDisplayImeController.addPositionProcessor(mDividerView);
}
/**
@@ -137,7 +132,6 @@
*/
void release() {
if (mDividerView != null) {
- mDisplayImeController.removePositionProcessor(mDividerView);
mDividerView = null;
}
@@ -152,6 +146,11 @@
}
}
+ void setInteractive(boolean interactive) {
+ if (mDividerView == null) return;
+ mDividerView.setInteractive(interactive);
+ }
+
void setResizingSplits(boolean resizing) {
if (resizing == mResizingSplits) return;
try {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java
index 9a09ca4..9bcc3ac 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java
@@ -29,14 +29,14 @@
import static android.content.Intent.EXTRA_TASK_ID;
import static android.content.Intent.EXTRA_USER;
+import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_BOTTOM_OR_RIGHT;
+import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_TOP_OR_LEFT;
+import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_UNDEFINED;
import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_FULLSCREEN;
import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPLIT_BOTTOM;
import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPLIT_LEFT;
import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPLIT_RIGHT;
import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPLIT_TOP;
-import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_POSITION_BOTTOM_OR_RIGHT;
-import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_POSITION_TOP_OR_LEFT;
-import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_POSITION_UNDEFINED;
import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_SIDE;
import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_UNDEFINED;
@@ -64,7 +64,7 @@
import androidx.annotation.VisibleForTesting;
import com.android.wm.shell.common.DisplayLayout;
-import com.android.wm.shell.splitscreen.SplitScreen.StagePosition;
+import com.android.wm.shell.common.split.SplitLayout.SplitPosition;
import com.android.wm.shell.splitscreen.SplitScreen.StageType;
import com.android.wm.shell.splitscreen.SplitScreenController;
@@ -203,10 +203,10 @@
final boolean leftOrTop = target.type == TYPE_SPLIT_TOP || target.type == TYPE_SPLIT_LEFT;
@StageType int stage = STAGE_TYPE_UNDEFINED;
- @StagePosition int position = STAGE_POSITION_UNDEFINED;
+ @SplitPosition int position = SPLIT_POSITION_UNDEFINED;
if (target.type != TYPE_FULLSCREEN && mSplitScreen != null) {
// Update launch options for the split side we are targeting.
- position = leftOrTop ? STAGE_POSITION_TOP_OR_LEFT : STAGE_POSITION_BOTTOM_OR_RIGHT;
+ position = leftOrTop ? SPLIT_POSITION_TOP_OR_LEFT : SPLIT_POSITION_BOTTOM_OR_RIGHT;
if (!inSplitScreen) {
// Launch in the side stage if we are not in split-screen already.
stage = STAGE_TYPE_SIDE;
@@ -219,7 +219,7 @@
}
private void startClipDescription(ClipDescription description, Intent intent,
- @StageType int stage, @StagePosition int position) {
+ @StageType int stage, @SplitPosition int position) {
final boolean isTask = description.hasMimeType(MIMETYPE_APPLICATION_TASK);
final boolean isShortcut = description.hasMimeType(MIMETYPE_APPLICATION_SHORTCUT);
final Bundle opts = intent.hasExtra(EXTRA_ACTIVITY_OPTIONS)
@@ -291,12 +291,12 @@
* Interface for actually committing the task launches.
*/
public interface Starter {
- void startTask(int taskId, @StageType int stage, @StagePosition int position,
+ void startTask(int taskId, @StageType int stage, @SplitPosition int position,
@Nullable Bundle options);
void startShortcut(String packageName, String shortcutId, @StageType int stage,
- @StagePosition int position, @Nullable Bundle options, UserHandle user);
+ @SplitPosition int position, @Nullable Bundle options, UserHandle user);
void startIntent(PendingIntent intent, Intent fillInIntent,
- @StageType int stage, @StagePosition int position,
+ @StageType int stage, @SplitPosition int position,
@Nullable Bundle options);
void enterSplitScreen(int taskId, boolean leftOrTop);
void exitSplitScreen();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerView.java
index 60f7ee2..7e4010d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerView.java
@@ -521,12 +521,14 @@
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
- mVelocityTracker.addMovement(event);
-
- if (!mMoving) break;
+ if (!mMoving) {
+ stopDragging();
+ break;
+ }
x = (int) event.getRawX();
y = (int) event.getRawY();
+ mVelocityTracker.addMovement(event);
mVelocityTracker.computeCurrentVelocity(1000);
int position = calculatePosition(x, y);
stopDragging(position, isHorizontalDivision() ? mVelocityTracker.getYVelocity()
@@ -685,9 +687,9 @@
mTmpRect.set(mHandle.getLeft(), mHandle.getTop(), mHandle.getRight(), mHandle.getBottom());
if (isHorizontalDivision()) {
- mTmpRect.offsetTo(0, mDividerPositionY);
+ mTmpRect.offsetTo(mHandle.getLeft(), mDividerPositionY);
} else {
- mTmpRect.offsetTo(mDividerPositionX, 0);
+ mTmpRect.offsetTo(mDividerPositionX, mHandle.getTop());
}
mWindowManagerProxy.setTouchRegion(mTmpRect);
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 9eacaec..ee2202a 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
@@ -577,7 +577,7 @@
mSplits.getSplitTransitions().dismissSplit(
mSplits, mSplitLayout, !toPrimaryTask, snapped);
} else {
- mWindowManagerProxy.applyDismissSplit(mSplits, mSplitLayout, !toPrimaryTask);
+ mWindowManagerProxy.applyDismissSplit(mSplits, mSplitLayout, !toPrimaryTask);
onDismissSplit();
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenTaskListener.java
index cf35656..86bf3ff 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenTaskListener.java
@@ -38,6 +38,7 @@
import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.common.SurfaceUtils;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.transition.Transitions;
@@ -70,9 +71,9 @@
private final LegacySplitScreenTransitions mSplitTransitions;
LegacySplitScreenTaskListener(LegacySplitScreenController splitScreenController,
- ShellTaskOrganizer shellTaskOrganizer,
- Transitions transitions,
- SyncTransactionQueue syncQueue) {
+ ShellTaskOrganizer shellTaskOrganizer,
+ Transitions transitions,
+ SyncTransactionQueue syncQueue) {
mSplitScreenController = splitScreenController;
mTaskOrganizer = shellTaskOrganizer;
mSplitTransitions = new LegacySplitScreenTransitions(splitScreenController.mTransactionPool,
@@ -146,21 +147,11 @@
ProtoLog.v(WM_SHELL_TASK_ORG, "%s onTaskAppeared Supported", TAG);
// Initialize dim surfaces:
- mPrimaryDim = new SurfaceControl.Builder(mSurfaceSession)
- .setParent(mPrimarySurface).setColorLayer()
- .setName("Primary Divider Dim")
- .setCallsite("SplitScreenTaskOrganizer.onTaskAppeared")
- .build();
- mSecondaryDim = new SurfaceControl.Builder(mSurfaceSession)
- .setParent(mSecondarySurface).setColorLayer()
- .setName("Secondary Divider Dim")
- .setCallsite("SplitScreenTaskOrganizer.onTaskAppeared")
- .build();
SurfaceControl.Transaction t = getTransaction();
- t.setLayer(mPrimaryDim, Integer.MAX_VALUE);
- t.setColor(mPrimaryDim, new float[]{0f, 0f, 0f});
- t.setLayer(mSecondaryDim, Integer.MAX_VALUE);
- t.setColor(mSecondaryDim, new float[]{0f, 0f, 0f});
+ mPrimaryDim = SurfaceUtils.makeDimLayer(
+ t, mPrimarySurface, "Primary Divider Dim", mSurfaceSession);
+ mSecondaryDim = SurfaceUtils.makeDimLayer(
+ t, mSecondarySurface, "Secondary Divider Dim", mSurfaceSession);
t.apply();
releaseTransaction(t);
}
@@ -203,6 +194,22 @@
return;
}
synchronized (this) {
+ if (!taskInfo.supportsMultiWindow) {
+ if (mSplitScreenController.isDividerVisible()) {
+ // Dismiss the split screen if the task no longer supports multi window.
+ if (taskInfo.taskId == mPrimary.taskId
+ || taskInfo.parentTaskId == mPrimary.taskId) {
+ // If the primary is focused, dismiss to primary.
+ mSplitScreenController
+ .startDismissSplit(taskInfo.isFocused /* toPrimaryTask */);
+ } else {
+ // If the secondary is not focused, dismiss to primary.
+ mSplitScreenController
+ .startDismissSplit(!taskInfo.isFocused /* toPrimaryTask */);
+ }
+ }
+ return;
+ }
if (taskInfo.hasParentTask()) {
// changed messages are noisy since it reports on every ensureVisibility. This
// conflicts with legacy app-transitions which "swaps" the position to a
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/WindowManagerProxy.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/WindowManagerProxy.java
index 1072845..e42e43b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/WindowManagerProxy.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/WindowManagerProxy.java
@@ -41,6 +41,7 @@
import android.window.WindowContainerTransaction;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.ArrayUtils;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.transition.Transitions;
@@ -214,8 +215,12 @@
if (!rootTask.supportsMultiWindow && rootTask.topActivityType != ACTIVITY_TYPE_HOME) {
continue;
}
- // Only move fullscreen tasks to split secondary.
- if (rootTask.getWindowingMode() != WINDOWING_MODE_FULLSCREEN) {
+ // Only move split controlling tasks to split secondary.
+ final int windowingMode = rootTask.getWindowingMode();
+ if (!ArrayUtils.contains(CONTROLLED_WINDOWING_MODES, windowingMode)
+ || !ArrayUtils.contains(CONTROLLED_ACTIVITY_TYPES, rootTask.getActivityType())
+ // Excludes split screen secondary due to it's the root we're reparenting to.
+ || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
continue;
}
// Since this iterates from bottom to top, update topHomeTask for every fullscreen task
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHanded.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHanded.java
index 242f8f1..8dc05de9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHanded.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHanded.java
@@ -19,7 +19,6 @@
import android.content.res.Configuration;
import com.android.wm.shell.common.annotations.ExternalThread;
-import com.android.wm.shell.onehanded.OneHandedGestureHandler.OneHandedGestureEventCallback;
/**
* Interface to engage one handed feature.
@@ -60,11 +59,6 @@
void stopOneHanded(int uiEvent);
/**
- * Sets navigation 3 button mode enabled or disabled by users.
- */
- void setThreeButtonModeEnabled(boolean enabled);
-
- /**
* Sets one handed feature temporary locked in enabled or disabled state, this won't change
* settings configuration.
*
@@ -80,12 +74,6 @@
void registerTransitionCallback(OneHandedTransitionCallback callback);
/**
- * Registers callback for one handed gesture, this gesture callback will be activated on
- * 3 button navigation mode only
- */
- void registerGestureCallback(OneHandedGestureEventCallback callback);
-
- /**
* Receive onConfigurationChanged() events
*/
void onConfigChanged(Configuration newConfig);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedAnimationController.java
index 7e5fd92..1ae2636 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedAnimationController.java
@@ -19,6 +19,7 @@
import android.animation.Animator;
import android.animation.ValueAnimator;
import android.annotation.IntDef;
+import android.annotation.Nullable;
import android.content.Context;
import android.graphics.Rect;
import android.view.SurfaceControl;
@@ -203,8 +204,10 @@
}
OneHandedTransitionAnimator addOneHandedAnimationCallback(
- OneHandedAnimationCallback callback) {
- mOneHandedAnimationCallbacks.add(callback);
+ @Nullable OneHandedAnimationCallback callback) {
+ if (callback != null) {
+ mOneHandedAnimationCallbacks.add(callback);
+ }
return this;
}
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 ce57638..49266ce 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
@@ -41,7 +41,6 @@
import android.provider.Settings;
import android.util.Slog;
import android.view.Surface;
-import android.view.ViewConfiguration;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityManager;
@@ -59,7 +58,6 @@
import com.android.wm.shell.common.TaskStackListenerCallback;
import com.android.wm.shell.common.TaskStackListenerImpl;
import com.android.wm.shell.common.annotations.ExternalThread;
-import com.android.wm.shell.onehanded.OneHandedGestureHandler.OneHandedGestureEventCallback;
import java.io.PrintWriter;
@@ -101,7 +99,6 @@
private final OneHandedImpl mImpl = new OneHandedImpl();
private OneHandedDisplayAreaOrganizer mDisplayAreaOrganizer;
- private OneHandedGestureHandler mGestureHandler;
private OneHandedBackgroundPanelOrganizer mBackgroundPanelOrganizer;
/**
@@ -113,7 +110,6 @@
return;
}
mDisplayAreaOrganizer.onRotateDisplay(mContext, toRotation, wct);
- mGestureHandler.onRotateDisplay(mDisplayAreaOrganizer.getDisplayLayout());
};
private final DisplayController.OnDisplaysChangedListener mDisplaysChangedListener =
@@ -196,7 +192,7 @@
private boolean isInitialized() {
if (mDisplayAreaOrganizer == null || mDisplayController == null
- || mGestureHandler == null || mOneHandedSettingsUtil == null) {
+ || mOneHandedSettingsUtil == null) {
Slog.w(TAG, "Components may not initialized yet!");
return false;
}
@@ -221,13 +217,11 @@
OneHandedTimeoutHandler timeoutHandler = new OneHandedTimeoutHandler(mainExecutor);
OneHandedState transitionState = new OneHandedState();
OneHandedTutorialHandler tutorialHandler = new OneHandedTutorialHandler(context,
- displayLayout, windowManager, mainExecutor);
+ displayLayout, windowManager, settingsUtil, mainExecutor);
OneHandedAnimationController animationController =
new OneHandedAnimationController(context);
OneHandedTouchHandler touchHandler = new OneHandedTouchHandler(timeoutHandler,
mainExecutor);
- OneHandedGestureHandler gestureHandler = new OneHandedGestureHandler(
- context, displayLayout, ViewConfiguration.get(context), mainExecutor);
OneHandedBackgroundPanelOrganizer oneHandedBackgroundPanelOrganizer =
new OneHandedBackgroundPanelOrganizer(context, displayLayout, mainExecutor);
OneHandedDisplayAreaOrganizer organizer = new OneHandedDisplayAreaOrganizer(
@@ -238,7 +232,7 @@
ServiceManager.getService(Context.OVERLAY_SERVICE));
return new OneHandedController(context, displayController,
oneHandedBackgroundPanelOrganizer, organizer, touchHandler, tutorialHandler,
- gestureHandler, settingsUtil, accessibilityUtil, timeoutHandler, transitionState,
+ settingsUtil, accessibilityUtil, timeoutHandler, transitionState,
oneHandedUiEventsLogger, overlayManager, taskStackListener, mainExecutor,
mainHandler);
}
@@ -250,7 +244,6 @@
OneHandedDisplayAreaOrganizer displayAreaOrganizer,
OneHandedTouchHandler touchHandler,
OneHandedTutorialHandler tutorialHandler,
- OneHandedGestureHandler gestureHandler,
OneHandedSettingsUtil settingsUtil,
OneHandedAccessibilityUtil oneHandedAccessibilityUtil,
OneHandedTimeoutHandler timeoutHandler,
@@ -269,7 +262,6 @@
mTouchHandler = touchHandler;
mState = state;
mTutorialHandler = tutorialHandler;
- mGestureHandler = gestureHandler;
mOverlayManager = overlayManager;
mMainExecutor = mainExecutor;
mMainHandler = mainHandler;
@@ -307,6 +299,8 @@
mAccessibilityManager = AccessibilityManager.getInstance(context);
mAccessibilityManager.addAccessibilityStateChangeListener(
mAccessibilityStateChangeListener);
+
+ mState.addSListeners(mTutorialHandler);
}
public OneHanded asOneHanded() {
@@ -399,24 +393,15 @@
mOneHandedUiEventLogger.writeEvent(uiEvent);
}
- private void setThreeButtonModeEnabled(boolean enabled) {
- mGestureHandler.onThreeButtonModeEnabled(enabled);
- }
-
@VisibleForTesting
void registerTransitionCallback(OneHandedTransitionCallback callback) {
mDisplayAreaOrganizer.registerTransitionCallback(callback);
}
- private void registerGestureCallback(OneHandedGestureEventCallback callback) {
- mGestureHandler.setGestureEventListener(callback);
- }
-
private void setupCallback() {
mTouchHandler.registerTouchEventListener(() ->
stopOneHanded(OneHandedUiEventLogger.EVENT_ONE_HANDED_TRIGGER_OVERSPACE_OUT));
mDisplayAreaOrganizer.registerTransitionCallback(mTouchHandler);
- mDisplayAreaOrganizer.registerTransitionCallback(mGestureHandler);
mDisplayAreaOrganizer.registerTransitionCallback(mTutorialHandler);
mDisplayAreaOrganizer.registerTransitionCallback(mBackgroundPanelOrganizer);
mDisplayAreaOrganizer.registerTransitionCallback(mTransitionCallBack);
@@ -465,7 +450,6 @@
private void updateDisplayLayout(int displayId) {
final DisplayLayout newDisplayLayout = mDisplayController.getDisplayLayout(displayId);
mDisplayAreaOrganizer.setDisplayLayout(newDisplayLayout);
- mGestureHandler.onDisplayChanged(newDisplayLayout);
mTutorialHandler.onDisplayChanged(newDisplayLayout);
}
@@ -588,7 +572,6 @@
}
mTouchHandler.onOneHandedEnabled(mIsOneHandedEnabled);
- mGestureHandler.onGestureEnabled(mIsOneHandedEnabled || mIsSwipeToNotificationEnabled);
if (!mIsOneHandedEnabled) {
mDisplayAreaOrganizer.unregisterOrganizer();
@@ -643,19 +626,16 @@
return;
}
mLockedDisabled = locked && !enabled;
-
- // Disabled gesture when keyguard ON
- mGestureHandler.onGestureEnabled(!mLockedDisabled && isFeatureEnabled);
}
private void onConfigChanged(Configuration newConfig) {
- if (mTutorialHandler != null) {
- if (!mIsOneHandedEnabled
- || newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
- return;
- }
- mTutorialHandler.onConfigurationChanged(newConfig);
+ if (mTutorialHandler == null) {
+ return;
}
+ if (!mIsOneHandedEnabled || newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
+ return;
+ }
+ mTutorialHandler.onConfigurationChanged();
}
private void onUserSwitch(int newUserId) {
@@ -685,10 +665,6 @@
mDisplayAreaOrganizer.dump(pw);
}
- if (mGestureHandler != null) {
- mGestureHandler.dump(pw);
- }
-
if (mTouchHandler != null) {
mTouchHandler.dump(pw);
}
@@ -775,13 +751,6 @@
}
@Override
- public void setThreeButtonModeEnabled(boolean enabled) {
- mMainExecutor.execute(() -> {
- OneHandedController.this.setThreeButtonModeEnabled(enabled);
- });
- }
-
- @Override
public void setLockedDisabled(boolean locked, boolean enabled) {
mMainExecutor.execute(() -> {
OneHandedController.this.setLockedDisabled(locked, enabled);
@@ -796,13 +765,6 @@
}
@Override
- public void registerGestureCallback(OneHandedGestureEventCallback callback) {
- mMainExecutor.execute(() -> {
- OneHandedController.this.registerGestureCallback(callback);
- });
- }
-
- @Override
public void onConfigChanged(Configuration newConfig) {
mMainExecutor.execute(() -> {
OneHandedController.this.onConfigChanged(newConfig);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedGestureHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedGestureHandler.java
deleted file mode 100644
index 0383229..0000000
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedGestureHandler.java
+++ /dev/null
@@ -1,308 +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.
- */
-
-package com.android.wm.shell.onehanded;
-
-import static android.view.Display.DEFAULT_DISPLAY;
-
-import android.annotation.Nullable;
-import android.content.Context;
-import android.graphics.PointF;
-import android.graphics.Rect;
-import android.hardware.input.InputManager;
-import android.os.Looper;
-import android.view.Display;
-import android.view.InputChannel;
-import android.view.InputEvent;
-import android.view.InputEventReceiver;
-import android.view.InputMonitor;
-import android.view.MotionEvent;
-import android.view.Surface;
-import android.view.ViewConfiguration;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.VisibleForTesting;
-
-import com.android.wm.shell.R;
-import com.android.wm.shell.common.DisplayLayout;
-import com.android.wm.shell.common.ShellExecutor;
-
-import java.io.PrintWriter;
-
-/**
- * The class manage swipe up and down gesture for 3-Button mode navigation, others(e.g, 2-button,
- * full gesture mode) are handled by Launcher quick steps. TODO(b/160934654) Migrate to Launcher
- * quick steps
- */
-public class OneHandedGestureHandler implements OneHandedTransitionCallback {
- private static final String TAG = "OneHandedGestureHandler";
-
- private static final int ANGLE_MAX = 150;
- private static final int ANGLE_MIN = 30;
- private final float mDragDistThreshold;
- private final float mSquaredSlop;
- private final PointF mDownPos = new PointF();
- private final PointF mLastPos = new PointF();
- private final PointF mStartDragPos = new PointF();
-
- private boolean mPassedSlop;
- private boolean mAllowGesture;
- private boolean mIsEnabled;
- private int mNavGestureHeight;
- private boolean mIsThreeButtonModeEnabled;
- private int mRotation = Surface.ROTATION_0;
-
- @VisibleForTesting
- InputMonitor mInputMonitor;
- @VisibleForTesting
- InputEventReceiver mInputEventReceiver;
- private final ShellExecutor mMainExecutor;
- @VisibleForTesting
- @Nullable
- OneHandedGestureEventCallback mGestureEventCallback;
- private Rect mGestureRegion = new Rect();
- private boolean mIsStopGesture;
-
- /**
- * Constructor of OneHandedGestureHandler, we only handle the gesture of {@link
- * Display#DEFAULT_DISPLAY}
- *
- * @param context Any context
- * @param displayLayout Current {@link DisplayLayout} from controller
- * @param viewConfig {@link ViewConfiguration} to obtain touch slop
- * @param mainExecutor The wm-shell main executor
- */
- public OneHandedGestureHandler(Context context,
- DisplayLayout displayLayout,
- ViewConfiguration viewConfig,
- ShellExecutor mainExecutor) {
- mMainExecutor = mainExecutor;
- mDragDistThreshold = context.getResources().getDimensionPixelSize(
- R.dimen.gestures_onehanded_drag_threshold);
-
- final float slop = viewConfig.getScaledTouchSlop();
- mSquaredSlop = slop * slop;
- onDisplayChanged(displayLayout);
- updateIsEnabled();
- }
-
- /**
- * Notifies by {@link OneHandedController}, when swipe down gesture is enabled on 3 button
- * navigation bar mode.
- *
- * @param isEnabled Either one handed mode or swipe for notification function enabled or not
- */
- public void onGestureEnabled(boolean isEnabled) {
- mIsEnabled = isEnabled;
- updateIsEnabled();
- }
-
- void onThreeButtonModeEnabled(boolean isEnabled) {
- mIsThreeButtonModeEnabled = isEnabled;
- updateIsEnabled();
- }
-
- /**
- * Registers {@link OneHandedGestureEventCallback} to receive onStart(), onStop() callback
- */
- public void setGestureEventListener(OneHandedGestureEventCallback callback) {
- mGestureEventCallback = callback;
- }
-
- /**
- * Called when onDisplayAdded() or onDisplayRemoved() callback
- * @param displayLayout The latest {@link DisplayLayout} representing current displayId
- */
- public void onDisplayChanged(DisplayLayout displayLayout) {
- mNavGestureHeight = getNavBarSize(displayLayout);
- mGestureRegion.set(0, displayLayout.height() - mNavGestureHeight, displayLayout.width(),
- displayLayout.height());
- mRotation = displayLayout.rotation();
- }
-
- private void onMotionEvent(MotionEvent ev) {
- int action = ev.getActionMasked();
- if (action == MotionEvent.ACTION_DOWN) {
- mAllowGesture = isWithinTouchRegion(ev.getX(), ev.getY()) && isGestureAvailable();
- if (mAllowGesture) {
- mDownPos.set(ev.getX(), ev.getY());
- mLastPos.set(mDownPos);
- }
- } else if (mAllowGesture) {
- switch (action) {
- case MotionEvent.ACTION_MOVE:
- mLastPos.set(ev.getX(), ev.getY());
- if (!mPassedSlop) {
- if (squaredHypot(mLastPos.x - mDownPos.x, mLastPos.y - mDownPos.y)
- > mSquaredSlop) {
- mStartDragPos.set(mLastPos.x, mLastPos.y);
- if (isValidStartAngle(
- mDownPos.x - mLastPos.x, mDownPos.y - mLastPos.y)
- || isValidExitAngle(
- mDownPos.x - mLastPos.x, mDownPos.y - mLastPos.y)) {
- mPassedSlop = true;
- mInputMonitor.pilferPointers();
- }
- }
- } else {
- float distance = (float) Math.hypot(mLastPos.x - mDownPos.x,
- mLastPos.y - mDownPos.y);
- if (distance > mDragDistThreshold) {
- mIsStopGesture = true;
- }
- }
- break;
- case MotionEvent.ACTION_UP:
- if (mLastPos.y >= mDownPos.y && mPassedSlop) {
- mGestureEventCallback.onStart();
- } else if (mIsStopGesture) {
- mGestureEventCallback.onStop();
- }
- clearState();
- break;
- case MotionEvent.ACTION_CANCEL:
- clearState();
- break;
- default:
- break;
- }
- }
- }
-
- private void clearState() {
- mPassedSlop = false;
- mIsStopGesture = false;
- }
-
- private void disposeInputChannel() {
- if (mInputEventReceiver != null) {
- mInputEventReceiver.dispose();
- mInputEventReceiver = null;
- }
-
- if (mInputMonitor != null) {
- mInputMonitor.dispose();
- mInputMonitor = null;
- }
- }
-
- private boolean isWithinTouchRegion(float x, float y) {
- return mGestureRegion.contains(Math.round(x), Math.round(y));
- }
-
- private int getNavBarSize(@NonNull DisplayLayout displayLayout) {
- return isGestureAvailable() ? displayLayout.navBarFrameHeight() : 0 /* In landscape */;
- }
-
- private void updateIsEnabled() {
- disposeInputChannel();
-
- if (mIsEnabled && mIsThreeButtonModeEnabled && isGestureAvailable()) {
- mInputMonitor = InputManager.getInstance().monitorGestureInput(
- "onehanded-gesture-offset", DEFAULT_DISPLAY);
- try {
- mMainExecutor.executeBlocking(() -> {
- mInputEventReceiver = new EventReceiver(
- mInputMonitor.getInputChannel(), Looper.myLooper());
- });
- } catch (InterruptedException e) {
- throw new RuntimeException("Failed to create input event receiver", e);
- }
- }
- }
-
- private void onInputEvent(InputEvent ev) {
- if (ev instanceof MotionEvent) {
- onMotionEvent((MotionEvent) ev);
- }
- }
-
- /**
- * Handler for display rotation changes by {@link DisplayLayout}
- *
- * @param displayLayout The rotated displayLayout
- */
- public void onRotateDisplay(DisplayLayout displayLayout) {
- mRotation = displayLayout.rotation();
- mNavGestureHeight = getNavBarSize(displayLayout);
- mGestureRegion.set(0, displayLayout.height() - mNavGestureHeight, displayLayout.width(),
- displayLayout.height());
- updateIsEnabled();
- }
-
- // TODO: Use BatchedInputEventReceiver
- private class EventReceiver extends InputEventReceiver {
- EventReceiver(InputChannel channel, Looper looper) {
- super(channel, looper);
- }
-
- public void onInputEvent(InputEvent event) {
- OneHandedGestureHandler.this.onInputEvent(event);
- finishInputEvent(event, true);
- }
- }
-
- private boolean isGestureAvailable() {
- // Either OHM or swipe notification shade can activate in portrait mode only
- return mRotation == Surface.ROTATION_0 || mRotation == Surface.ROTATION_180;
- }
-
- private boolean isValidStartAngle(float deltaX, float deltaY) {
- final float angle = (float) Math.toDegrees(Math.atan2(deltaY, deltaX));
- return angle > -(ANGLE_MAX) && angle < -(ANGLE_MIN);
- }
-
- private boolean isValidExitAngle(float deltaX, float deltaY) {
- final float angle = (float) Math.toDegrees(Math.atan2(deltaY, deltaX));
- return angle > ANGLE_MIN && angle < ANGLE_MAX;
- }
-
- private float squaredHypot(float x, float y) {
- return x * x + y * y;
- }
-
- void dump(@NonNull PrintWriter pw) {
- final String innerPrefix = " ";
- pw.println(TAG);
- pw.print(innerPrefix + "mAllowGesture=");
- pw.println(mAllowGesture);
- pw.print(innerPrefix + "mIsEnabled=");
- pw.println(mIsEnabled);
- pw.print(innerPrefix + "mGestureRegion=");
- pw.println(mGestureRegion);
- pw.print(innerPrefix + "mNavGestureHeight=");
- pw.println(mNavGestureHeight);
- pw.print(innerPrefix + "mIsThreeButtonModeEnabled=");
- pw.println(mIsThreeButtonModeEnabled);
- pw.print(innerPrefix + "mRotation=");
- pw.println(mRotation);
- }
-
- /**
- * The touch(gesture) events to notify {@link OneHandedController} start or stop one handed
- */
- public interface OneHandedGestureEventCallback {
- /**
- * Handles the start gesture.
- */
- void onStart();
-
- /**
- * Handles the exit gesture.
- */
- void onStop();
- }
-}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java
index bb68224..90fc823 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java
@@ -29,7 +29,7 @@
import java.lang.annotation.RetentionPolicy;
/**
- * APIs for querying or updating one handed settings .
+ * APIs for querying or updating one handed settings.
*/
public final class OneHandedSettingsUtil {
private static final String TAG = "OneHandedSettingsUtil";
@@ -62,7 +62,7 @@
public static final int ONE_HANDED_TIMEOUT_LONG_IN_SECONDS = 12;
/**
- * Register one handed preference settings observer
+ * Registers one handed preference settings observer
*
* @param key Setting key to monitor in observer
* @param resolver ContentResolver of context
@@ -82,7 +82,7 @@
}
/**
- * Unregister one handed preference settings observer
+ * Unregisters one handed preference settings observer.
*
* @param resolver ContentResolver of context
* @param observer preference key change observer
@@ -95,7 +95,7 @@
}
/**
- * Query one handed enable or disable flag from Settings provider.
+ * Queries one handed enable or disable flag from Settings provider.
*
* @return enable or disable one handed mode flag.
*/
@@ -105,7 +105,7 @@
}
/**
- * Query taps app to exit config from Settings provider.
+ * Queries taps app to exit config from Settings provider.
*
* @return enable or disable taps app exit.
*/
@@ -115,7 +115,7 @@
}
/**
- * Query timeout value from Settings provider. Default is
+ * Queries timeout value from Settings provider. Default is.
* {@link OneHandedSettingsUtil#ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS}
*
* @return timeout value in seconds.
@@ -135,10 +135,31 @@
Settings.Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED, 0, userId) == 1;
}
+
/**
- * Sets one handed activated or not to notify state for shortcut
+ * Queries tutorial shown counts from Settings provider. Default is 0.
*
- * @return activated or not
+ * @return counts tutorial shown counts.
+ */
+ public int getTutorialShownCounts(ContentResolver resolver, int userId) {
+ return Settings.Secure.getIntForUser(resolver,
+ Settings.Secure.ONE_HANDED_TUTORIAL_SHOW_COUNT, 0, userId);
+ }
+
+ /**
+ * Sets tutorial shown counts.
+ *
+ * @return true if the value was set, false on database errors.
+ */
+ public boolean setTutorialShownCounts(ContentResolver resolver, int shownCounts, int userId) {
+ return Settings.Secure.putIntForUser(resolver,
+ Settings.Secure.ONE_HANDED_TUTORIAL_SHOW_COUNT, shownCounts, userId);
+ }
+
+ /**
+ * Sets one handed activated or not to notify state for shortcut.
+ *
+ * @return true if one handed mode is activated.
*/
public boolean getOneHandedModeActivated(ContentResolver resolver, int userId) {
return Settings.Secure.getIntForUser(resolver,
@@ -146,9 +167,9 @@
}
/**
- * Sets one handed activated or not to notify state for shortcut
+ * Sets one handed activated or not to notify state for shortcut.
*
- * @return activated or not
+ * @return true if the value was set, false on database errors.
*/
public boolean setOneHandedModeActivated(ContentResolver resolver, int state, int userId) {
return Settings.Secure.putIntForUser(resolver,
@@ -167,6 +188,8 @@
pw.println(getSettingsTapsAppToExit(resolver, userId));
pw.print(innerPrefix + "shortcutActivated=");
pw.println(getOneHandedModeActivated(resolver, userId));
+ pw.print(innerPrefix + "tutorialShownCounts=");
+ pw.println(getTutorialShownCounts(resolver, userId));
}
public OneHandedSettingsUtil() {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedState.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedState.java
index facc4bd..47bb99d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedState.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedState.java
@@ -21,6 +21,8 @@
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.List;
/**
Represents current OHM state by following steps, a generic CUJ is
@@ -28,13 +30,13 @@
*/
public class OneHandedState {
/** DEFAULT STATE after OHM feature initialized. */
- public static final int STATE_NONE = 0x00000000;
+ public static final int STATE_NONE = 0;
/** The state flag set when user trigger OHM. */
- public static final int STATE_ENTERING = 0x00000001;
+ public static final int STATE_ENTERING = 1;
/** The state flag set when transitioning */
- public static final int STATE_ACTIVE = 0x00000002;
+ public static final int STATE_ACTIVE = 2;
/** The state flag set when user stop OHM feature. */
- public static final int STATE_EXITING = 0x00000004;
+ public static final int STATE_EXITING = 3;
@IntDef(prefix = { "STATE_" }, value = {
STATE_NONE,
@@ -54,9 +56,18 @@
private static final String TAG = OneHandedState.class.getSimpleName();
+ private List<OnStateChangedListener> mStateChangeListeners = new ArrayList<>();
+
+ /**
+ * Adds listener to be called back when one handed state changed.
+ * @param listener the listener to be called back
+ */
+ public void addSListeners(OnStateChangedListener listener) {
+ mStateChangeListeners.add(listener);
+ }
+
/**
* Gets current transition state of One handed mode.
- *
* @return The bitwise flags representing current states.
*/
public @State int getState() {
@@ -85,6 +96,9 @@
*/
public void setState(@State int newState) {
sCurrentState = newState;
+ if (!mStateChangeListeners.isEmpty()) {
+ mStateChangeListeners.forEach((listener) -> listener.onStateChanged(newState));
+ }
}
/** Dumps internal state. */
@@ -93,4 +107,14 @@
pw.println(TAG);
pw.println(innerPrefix + "sCurrentState=" + sCurrentState);
}
+
+ /**
+ * Gets notified when one handed state changed
+ *
+ * @see OneHandedState
+ */
+ public interface OnStateChangedListener {
+ /** Called when one handed state changed */
+ default void onStateChanged(@State int newState) {}
+ }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTouchHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTouchHandler.java
index 0f9b320..5b9f0c4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTouchHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTouchHandler.java
@@ -37,7 +37,6 @@
/**
* Manages all the touch handling for One Handed on the Phone, including user tap outside region
* to exit, reset timer when user is in one-handed mode.
- * Refer {@link OneHandedGestureHandler} to see start and stop one handed gesture
*/
public class OneHandedTouchHandler implements OneHandedTransitionCallback {
private static final String TAG = "OneHandedTouchHandler";
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTutorialHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTutorialHandler.java
index e8cee8a..6cee404 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTutorialHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTutorialHandler.java
@@ -16,13 +16,19 @@
package com.android.wm.shell.onehanded;
+import static android.os.UserHandle.myUserId;
+
+import static com.android.wm.shell.onehanded.OneHandedState.STATE_ACTIVE;
+import static com.android.wm.shell.onehanded.OneHandedState.STATE_ENTERING;
+import static com.android.wm.shell.onehanded.OneHandedState.STATE_EXITING;
+import static com.android.wm.shell.onehanded.OneHandedState.STATE_NONE;
+
+import android.annotation.Nullable;
import android.content.ContentResolver;
import android.content.Context;
-import android.content.res.Configuration;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.os.SystemProperties;
-import android.provider.Settings;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
@@ -32,6 +38,7 @@
import androidx.annotation.NonNull;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.wm.shell.R;
import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.common.ShellExecutor;
@@ -39,42 +46,33 @@
import java.io.PrintWriter;
/**
- * Manages the user tutorial handling for One Handed operations, including animations synchronized
- * with one-handed translation.
- * Refer {@link OneHandedGestureHandler} and {@link OneHandedTouchHandler} to see start and stop
- * one handed gesture
+ * Handles tutorial visibility and synchronized transition for One Handed operations,
+ * TargetViewContainer only be created and attach to window when
+ * shown counts < {@link MAX_TUTORIAL_SHOW_COUNT}, and detach TargetViewContainer from window
+ * after exiting one handed mode.
*/
-public class OneHandedTutorialHandler implements OneHandedTransitionCallback {
+public class OneHandedTutorialHandler implements OneHandedTransitionCallback,
+ OneHandedState.OnStateChangedListener {
private static final String TAG = "OneHandedTutorialHandler";
private static final String ONE_HANDED_MODE_OFFSET_PERCENTAGE =
"persist.debug.one_handed_offset_percentage";
private static final int MAX_TUTORIAL_SHOW_COUNT = 2;
- private final WindowManager mWindowManager;
- private final String mPackageName;
+
private final float mTutorialHeightRatio;
+ private final WindowManager mWindowManager;
+ private final OneHandedSettingsUtil mSettingsUtil;
+ private final ShellExecutor mShellExecutor;
+
+ private boolean mCanShow;
+ private @OneHandedState.State int mCurrentState;
+ private int mShownCounts;
+ private int mTutorialAreaHeight;
private Context mContext;
- private Rect mDisplayBounds;
- private View mTutorialView;
private ContentResolver mContentResolver;
- private boolean mCanShowTutorial;
- private boolean mIsOneHandedMode;
-
- private enum ONE_HANDED_TRIGGER_STATE {
- UNSET, ENTERING, EXITING
- }
- /**
- * Current One-Handed trigger state.
- * Note: This is a dynamic state, whenever last state has been confirmed
- * (i.e. onStartFinished() or onStopFinished()), the state should be set "UNSET" at final.
- */
- private ONE_HANDED_TRIGGER_STATE mTriggerState = ONE_HANDED_TRIGGER_STATE.UNSET;
-
- /**
- * Container of the tutorial panel showing at outside region when one handed starting
- */
- private ViewGroup mTargetViewContainer;
- private int mTutorialAreaHeight;
+ private Rect mDisplayBounds;
+ private @Nullable View mTutorialView;
+ private @Nullable ViewGroup mTargetViewContainer;
private final OneHandedAnimationCallback mAnimationCallback = new OneHandedAnimationCallback() {
@Override
@@ -82,63 +80,51 @@
if (!canShowTutorial()) {
return;
}
- mTargetViewContainer.setVisibility(View.VISIBLE);
mTargetViewContainer.setTransitionGroup(true);
mTargetViewContainer.setTranslationY(yPos - mTargetViewContainer.getHeight());
}
-
- @Override
- public void onOneHandedAnimationStart(
- OneHandedAnimationController.OneHandedTransitionAnimator animator) {
- final float startValue = (float) animator.getStartValue();
- if (mTriggerState == ONE_HANDED_TRIGGER_STATE.UNSET) {
- mTriggerState = (startValue == 0f)
- ? ONE_HANDED_TRIGGER_STATE.ENTERING : ONE_HANDED_TRIGGER_STATE.EXITING;
- if (mCanShowTutorial && mTriggerState == ONE_HANDED_TRIGGER_STATE.ENTERING) {
- attachTurtorialTarget();
- }
- }
- }
};
public OneHandedTutorialHandler(Context context, DisplayLayout displayLayout,
- WindowManager windowManager, ShellExecutor mainExecutor) {
+ WindowManager windowManager, OneHandedSettingsUtil settingsUtil,
+ ShellExecutor mainExecutor) {
mContext = context;
- mWindowManager = windowManager;
- mPackageName = context.getPackageName();
mContentResolver = context.getContentResolver();
+ mWindowManager = windowManager;
+ mSettingsUtil = settingsUtil;
+ mShellExecutor = mainExecutor;
final float offsetPercentageConfig = context.getResources().getFraction(
R.fraction.config_one_handed_offset, 1, 1);
final int sysPropPercentageConfig = SystemProperties.getInt(
ONE_HANDED_MODE_OFFSET_PERCENTAGE, Math.round(offsetPercentageConfig * 100.0f));
mTutorialHeightRatio = sysPropPercentageConfig / 100.0f;
- onDisplayChanged(displayLayout);
- mCanShowTutorial = (Settings.Secure.getInt(mContentResolver,
- Settings.Secure.ONE_HANDED_TUTORIAL_SHOW_COUNT, 0) >= MAX_TUTORIAL_SHOW_COUNT)
- ? false : true;
- mIsOneHandedMode = false;
-
- mainExecutor.execute(() -> {
- recreateTutorialView(mContext);
- });
+ mShownCounts = mSettingsUtil.getTutorialShownCounts(mContentResolver, myUserId());
}
@Override
- public void onStartFinished(Rect bounds) {
- updateFinished(View.VISIBLE, 0f);
- updateTutorialCount();
- mTriggerState = ONE_HANDED_TRIGGER_STATE.UNSET;
- }
-
- @Override
- public void onStopFinished(Rect bounds) {
- updateFinished(View.INVISIBLE, -mTargetViewContainer.getHeight());
- removeTutorialFromWindowManager();
- mTriggerState = ONE_HANDED_TRIGGER_STATE.UNSET;
+ public void onStateChanged(int newState) {
+ mCurrentState = newState;
+ if (!canShowTutorial()) {
+ return;
+ }
+ switch (newState) {
+ case STATE_ENTERING:
+ createViewAndAttachToWindow(mContext);
+ break;
+ case STATE_ACTIVE:
+ case STATE_EXITING:
+ // no - op
+ break;
+ case STATE_NONE:
+ removeTutorialFromWindowManager(true /* increment */);
+ break;
+ default:
+ break;
+ }
}
/**
- * Called when onDisplayAdded() or onDisplayRemoved() callback
+ * Called when onDisplayAdded() or onDisplayRemoved() callback.
* @param displayLayout The latest {@link DisplayLayout} representing current displayId
*/
public void onDisplayChanged(DisplayLayout displayLayout) {
@@ -151,38 +137,32 @@
mTutorialAreaHeight = Math.round(mDisplayBounds.height() * mTutorialHeightRatio);
}
- private void recreateTutorialView(Context context) {
- mTutorialView = LayoutInflater.from(context).inflate(R.layout.one_handed_tutorial,
- null);
- mTargetViewContainer = new FrameLayout(context);
- mTargetViewContainer.setClipChildren(false);
- mTargetViewContainer.addView(mTutorialView);
- mTargetViewContainer.setVisibility(mIsOneHandedMode ? View.VISIBLE : View.GONE);
- }
-
- private void updateFinished(int visible, float finalPosition) {
+ @VisibleForTesting
+ void createViewAndAttachToWindow(Context context) {
if (!canShowTutorial()) {
return;
}
- mIsOneHandedMode = (finalPosition == 0f) ? true : false;
- mTargetViewContainer.setVisibility(visible);
- mTargetViewContainer.setTranslationY(finalPosition);
+ mTutorialView = LayoutInflater.from(context).inflate(R.layout.one_handed_tutorial, null);
+ mTargetViewContainer = new FrameLayout(context);
+ mTargetViewContainer.setClipChildren(false);
+ mTargetViewContainer.addView(mTutorialView);
+
+ attachTargetToWindow();
}
- private void updateTutorialCount() {
- int showCount = Settings.Secure.getInt(mContentResolver,
- Settings.Secure.ONE_HANDED_TUTORIAL_SHOW_COUNT, 0);
- showCount = Math.min(MAX_TUTORIAL_SHOW_COUNT, showCount + 1);
- mCanShowTutorial = showCount < MAX_TUTORIAL_SHOW_COUNT;
- Settings.Secure.putInt(mContentResolver,
- Settings.Secure.ONE_HANDED_TUTORIAL_SHOW_COUNT, showCount);
+ @VisibleForTesting
+ boolean setTutorialShownCountIncrement() {
+ if (!canShowTutorial()) {
+ return false;
+ }
+ mShownCounts += 1;
+ return mSettingsUtil.setTutorialShownCounts(mContentResolver, mShownCounts, myUserId());
}
/**
- * Adds the tutorial target view to the WindowManager and update its layout, so it's ready
- * to be animated in.
+ * Adds the tutorial target view to the WindowManager and update its layout.
*/
- private void attachTurtorialTarget() {
+ private void attachTargetToWindow() {
if (!mTargetViewContainer.isAttachedToWindow()) {
try {
mWindowManager.addView(mTargetViewContainer, getTutorialTargetLayoutParams());
@@ -195,14 +175,18 @@
}
}
- private void removeTutorialFromWindowManager() {
- if (mTargetViewContainer.isAttachedToWindow()) {
+ @VisibleForTesting
+ void removeTutorialFromWindowManager(boolean increment) {
+ if (mTargetViewContainer != null && mTargetViewContainer.isAttachedToWindow()) {
mWindowManager.removeViewImmediate(mTargetViewContainer);
+ if (increment) {
+ setTutorialShownCountIncrement();
+ }
}
}
- OneHandedAnimationCallback getAnimationCallback() {
- return mAnimationCallback;
+ @Nullable OneHandedAnimationCallback getAnimationCallback() {
+ return canShowTutorial() ? mAnimationCallback : null /* Disabled */;
}
/**
@@ -222,38 +206,36 @@
return lp;
}
- void dump(@NonNull PrintWriter pw) {
- final String innerPrefix = " ";
- pw.println(TAG);
- pw.print(innerPrefix + "mTriggerState=");
- pw.println(mTriggerState);
- pw.print(innerPrefix + "mDisplayBounds=");
- pw.println(mDisplayBounds);
- pw.print(innerPrefix + "mTutorialAreaHeight=");
- pw.println(mTutorialAreaHeight);
- }
-
- private boolean canShowTutorial() {
- if (!mCanShowTutorial) {
- // Since canSHowTutorial() will be called in onAnimationUpdate() and we still need to
- // hide Tutorial text in the period of continuously onAnimationUpdate() API call,
- // so we have to hide mTargetViewContainer here.
- mTargetViewContainer.setVisibility(View.GONE);
- return false;
- }
- return true;
+ @VisibleForTesting
+ boolean canShowTutorial() {
+ return mCanShow = mShownCounts < MAX_TUTORIAL_SHOW_COUNT;
}
/**
* onConfigurationChanged events for updating tutorial text.
- * @param newConfig
*/
- public void onConfigurationChanged(Configuration newConfig) {
- if (!mCanShowTutorial) {
+ public void onConfigurationChanged() {
+ if (!canShowTutorial()) {
return;
}
- removeTutorialFromWindowManager();
- recreateTutorialView(mContext.createConfigurationContext(newConfig));
- attachTurtorialTarget();
+ removeTutorialFromWindowManager(false /* increment */);
+ if (mCurrentState == STATE_ENTERING || mCurrentState == STATE_ACTIVE) {
+ createViewAndAttachToWindow(mContext);
+ }
+ }
+
+ void dump(@NonNull PrintWriter pw) {
+ final String innerPrefix = " ";
+ pw.println(TAG);
+ pw.print(innerPrefix + "mCanShow=");
+ pw.println(mCanShow);
+ pw.print(innerPrefix + "mCurrentState=");
+ pw.println(mCurrentState);
+ pw.print(innerPrefix + "mDisplayBounds=");
+ pw.println(mDisplayBounds);
+ pw.print(innerPrefix + "mShownCounts=");
+ pw.println(mShownCounts);
+ pw.print(innerPrefix + "mTutorialAreaHeight=");
+ pw.println(mTutorialAreaHeight);
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/IPip.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/IPip.aidl
index a6ffa6e..ddc85f7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/IPip.aidl
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/IPip.aidl
@@ -17,6 +17,7 @@
package com.android.wm.shell.pip;
import android.app.PictureInPictureParams;
+import android.view.SurfaceControl;
import android.content.ComponentName;
import android.content.pm.ActivityInfo;
import android.graphics.Rect;
@@ -48,8 +49,10 @@
*
* @param componentName ComponentName represents the Activity
* @param destinationBounds the destination bounds the PiP window lands into
+ * @param overlay an optional overlay to fade out after entering PiP
*/
- oneway void stopSwipePipToHome(in ComponentName componentName, in Rect destinationBounds) = 2;
+ oneway void stopSwipePipToHome(in ComponentName componentName, in Rect destinationBounds,
+ in SurfaceControl overlay) = 2;
/**
* Sets listener to get pinned stack animation callbacks.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
index 17e0d1b..a2c6567 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
@@ -89,6 +89,11 @@
|| direction == TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN;
}
+ /** Whether the given direction represents removing PIP. */
+ public static boolean isRemovePipDirection(@TransitionDirection int direction) {
+ return direction == TRANSITION_DIRECTION_REMOVE_STACK;
+ }
+
private final PipSurfaceTransactionHelper mSurfaceTransactionHelper;
private final ThreadLocal<AnimationHandler> mSfAnimationHandlerThreadLocal =
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java
index 7b834b2..046c320 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java
@@ -367,7 +367,15 @@
* the default stack bounds when first entering PiP.
*/
public float getSnapFraction(Rect stackBounds) {
- return mSnapAlgorithm.getSnapFraction(stackBounds, getMovementBounds(stackBounds));
+ return getSnapFraction(stackBounds, getMovementBounds(stackBounds));
+ }
+
+ /**
+ * @return the default snap fraction to apply instead of the default gravity when calculating
+ * the default stack bounds when first entering PiP.
+ */
+ public float getSnapFraction(Rect stackBounds, Rect movementBounds) {
+ return mSnapAlgorithm.getSnapFraction(stackBounds, movementBounds);
}
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java
index 561dff0..e3674dc 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java
@@ -55,7 +55,7 @@
STASH_TYPE_RIGHT
})
@Retention(RetentionPolicy.SOURCE)
- @interface StashType {}
+ public @interface StashType {}
private static final String TAG = PipBoundsState.class.getSimpleName();
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 0633330..fe64769 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
@@ -39,6 +39,7 @@
import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_USER_RESIZE;
import static com.android.wm.shell.pip.PipAnimationController.isInPipDirection;
import static com.android.wm.shell.pip.PipAnimationController.isOutPipDirection;
+import static com.android.wm.shell.pip.PipAnimationController.isRemovePipDirection;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -70,6 +71,7 @@
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.animation.Interpolators;
import com.android.wm.shell.common.DisplayController;
+import com.android.wm.shell.common.ScreenshotUtils;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.common.annotations.ShellMainThread;
@@ -147,6 +149,7 @@
private final PipUiEventLogger mPipUiEventLoggerLogger;
private final int mEnterAnimationDuration;
private final int mExitAnimationDuration;
+ private final int mCrossFadeAnimationDuration;
private final PipSurfaceTransactionHelper mSurfaceTransactionHelper;
private final Optional<LegacySplitScreenController> mSplitScreenOptional;
protected final ShellTaskOrganizer mTaskOrganizer;
@@ -184,8 +187,17 @@
mDeferredAnimEndTransaction = tx;
return;
}
- finishResize(tx, destinationBounds, direction, animationType);
- sendOnPipTransitionFinished(direction);
+ final boolean isExitPipDirection = isOutPipDirection(direction)
+ || isRemovePipDirection(direction);
+ if (mState != State.EXITING_PIP || isExitPipDirection) {
+ // Finish resize as long as we're not exiting PIP, or, if we are, only if this is
+ // the end of an exit PIP animation.
+ // This is necessary in case there was a resize animation ongoing when exit PIP
+ // started, in which case the first resize will be skipped to let the exit
+ // operation handle the final resize out of PIP mode. See b/185306679.
+ finishResize(tx, destinationBounds, direction, animationType);
+ sendOnPipTransitionFinished(direction);
+ }
if (direction == TRANSITION_DIRECTION_TO_PIP) {
// TODO (b//169221267): Add jank listener for transactions without buffer updates.
//InteractionJankMonitor.getInstance().end(
@@ -257,6 +269,12 @@
*/
private boolean mInSwipePipToHomeTransition;
+ /**
+ * An optional overlay used to mask content changing between an app in/out of PiP, only set if
+ * {@link #mInSwipePipToHomeTransition} is true.
+ */
+ private SurfaceControl mSwipePipToHomeOverlay;
+
public PipTaskOrganizer(Context context,
@NonNull SyncTransactionQueue syncTransactionQueue,
@NonNull PipBoundsState pipBoundsState,
@@ -280,6 +298,8 @@
.getInteger(R.integer.config_pipEnterAnimationDuration);
mExitAnimationDuration = context.getResources()
.getInteger(R.integer.config_pipExitAnimationDuration);
+ mCrossFadeAnimationDuration = context.getResources()
+ .getInteger(R.integer.config_pipCrossfadeAnimationDuration);
mSurfaceTransactionHelper = surfaceTransactionHelper;
mPipAnimationController = pipAnimationController;
mPipUiEventLoggerLogger = pipUiEventLogger;
@@ -350,10 +370,12 @@
* Callback when launcher finishes swipe-pip-to-home operation.
* Expect {@link #onTaskAppeared(ActivityManager.RunningTaskInfo, SurfaceControl)} afterwards.
*/
- public void stopSwipePipToHome(ComponentName componentName, Rect destinationBounds) {
+ public void stopSwipePipToHome(ComponentName componentName, Rect destinationBounds,
+ SurfaceControl overlay) {
// do nothing if there is no startSwipePipToHome being called before
if (mInSwipePipToHomeTransition) {
mPipBoundsState.setBounds(destinationBounds);
+ mSwipePipToHomeOverlay = overlay;
}
}
@@ -599,6 +621,7 @@
private void onEndOfSwipePipToHomeTransition() {
final Rect destinationBounds = mPipBoundsState.getBounds();
+ final SurfaceControl swipeToHomeOverlay = mSwipePipToHomeOverlay;
final SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction();
mSurfaceTransactionHelper.resetScale(tx, mLeash, destinationBounds);
mSurfaceTransactionHelper.crop(tx, mLeash, destinationBounds);
@@ -607,8 +630,14 @@
// Ensure menu's settled in its final bounds first.
finishResizeForMenu(destinationBounds);
sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP);
+
+ // Remove the swipe to home overlay
+ if (swipeToHomeOverlay != null) {
+ fadeOutAndRemoveOverlay(swipeToHomeOverlay);
+ }
}, tx);
mInSwipePipToHomeTransition = false;
+ mSwipePipToHomeOverlay = null;
}
private void applyEnterPipSyncTransaction(Rect destinationBounds, Runnable runnable,
@@ -1101,6 +1130,7 @@
private void finishResize(SurfaceControl.Transaction tx, Rect destinationBounds,
@PipAnimationController.TransitionDirection int direction,
@PipAnimationController.AnimationType int type) {
+ final Rect preResizeBounds = new Rect(mPipBoundsState.getBounds());
mPipBoundsState.setBounds(destinationBounds);
if (direction == TRANSITION_DIRECTION_REMOVE_STACK) {
removePipImmediately();
@@ -1124,41 +1154,26 @@
&& mPictureInPictureParams != null
&& !mPictureInPictureParams.isSeamlessResizeEnabled();
if (animateCrossFadeResize) {
- // Take a snapshot of the PIP task and hide it. We'll show it and fade it out after
- // the wct transaction is applied and the activity is laid out again.
- final SurfaceControl snapshotSurface = mTaskOrganizer.takeScreenshot(mToken);
- mSurfaceTransactionHelper.reparentAndShowSurfaceSnapshot(
- mSurfaceControlTransactionFactory.getTransaction(), mLeash, snapshotSurface);
- mSyncTransactionQueue.queue(wct);
- mSyncTransactionQueue.runInSync(t -> {
- // Scale the snapshot from its pre-resize bounds to the post-resize bounds.
- final Rect snapshotSrc = new Rect(0, 0, snapshotSurface.getWidth(),
- snapshotSurface.getHeight());
- final Rect snapshotDest = new Rect(0, 0, destinationBounds.width(),
- destinationBounds.height());
- mSurfaceTransactionHelper.scale(t, snapshotSurface, snapshotSrc, snapshotDest);
+ // Take a snapshot of the PIP task and show it. We'll fade it out after the wct
+ // transaction is applied and the activity is laid out again.
+ preResizeBounds.offsetTo(0, 0);
+ final Rect snapshotDest = new Rect(0, 0, destinationBounds.width(),
+ destinationBounds.height());
+ final SurfaceControl snapshotSurface = ScreenshotUtils.takeScreenshot(
+ mSurfaceControlTransactionFactory.getTransaction(), mLeash, preResizeBounds);
+ if (snapshotSurface != null) {
+ mSyncTransactionQueue.queue(wct);
+ mSyncTransactionQueue.runInSync(t -> {
+ // Scale the snapshot from its pre-resize bounds to the post-resize bounds.
+ mSurfaceTransactionHelper.scale(t, snapshotSurface, preResizeBounds,
+ snapshotDest);
- // Start animation to fade out the snapshot.
- final ValueAnimator animator = ValueAnimator.ofFloat(1.0f, 0.0f);
- animator.setDuration(mEnterAnimationDuration);
- animator.addUpdateListener(animation -> {
- final float alpha = (float) animation.getAnimatedValue();
- final SurfaceControl.Transaction transaction =
- mSurfaceControlTransactionFactory.getTransaction();
- transaction.setAlpha(snapshotSurface, alpha);
- transaction.apply();
+ // Start animation to fade out the snapshot.
+ fadeOutAndRemoveOverlay(snapshotSurface);
});
- animator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- final SurfaceControl.Transaction tx =
- mSurfaceControlTransactionFactory.getTransaction();
- tx.remove(snapshotSurface);
- tx.apply();
- }
- });
- animator.start();
- });
+ } else {
+ applyFinishBoundsResize(wct, direction);
+ }
} else {
applyFinishBoundsResize(wct, direction);
}
@@ -1301,6 +1316,35 @@
}
/**
+ * Fades out and removes an overlay surface.
+ */
+ private void fadeOutAndRemoveOverlay(SurfaceControl surface) {
+ if (surface == null) {
+ return;
+ }
+
+ final ValueAnimator animator = ValueAnimator.ofFloat(1.0f, 0.0f);
+ animator.setDuration(mCrossFadeAnimationDuration);
+ animator.addUpdateListener(animation -> {
+ final float alpha = (float) animation.getAnimatedValue();
+ final SurfaceControl.Transaction transaction =
+ mSurfaceControlTransactionFactory.getTransaction();
+ transaction.setAlpha(surface, alpha);
+ transaction.apply();
+ });
+ animator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ final SurfaceControl.Transaction tx =
+ mSurfaceControlTransactionFactory.getTransaction();
+ tx.remove(surface);
+ tx.apply();
+ }
+ });
+ animator.start();
+ }
+
+ /**
* Dumps internal states.
*/
@Override
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 052653e..140f32f9 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
@@ -173,13 +173,6 @@
detachPipMenuView();
}
-
- void onPinnedStackAnimationEnded() {
- if (isMenuVisible()) {
- mPipMenuView.onPipAnimationEnded();
- }
- }
-
private void attachPipMenuView() {
// In case detach was not called (e.g. PIP unexpectedly closed)
if (mPipMenuView != null) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipAccessibilityInteractionConnection.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipAccessibilityInteractionConnection.java
index 3b65899..47a8c67 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipAccessibilityInteractionConnection.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipAccessibilityInteractionConnection.java
@@ -15,6 +15,8 @@
*/
package com.android.wm.shell.pip.phone;
+import static com.android.wm.shell.pip.PipBoundsState.STASH_TYPE_NONE;
+
import android.annotation.NonNull;
import android.content.Context;
import android.graphics.Rect;
@@ -59,6 +61,7 @@
private final PipTaskOrganizer mTaskOrganizer;
private final PipSnapAlgorithm mSnapAlgorithm;
private final Runnable mUpdateMovementBoundCallback;
+ private final Runnable mUnstashCallback;
private final AccessibilityCallbacks mCallbacks;
private final IAccessibilityInteractionConnection mConnectionImpl;
@@ -72,7 +75,7 @@
@NonNull PipBoundsState pipBoundsState, PipMotionHelper motionHelper,
PipTaskOrganizer taskOrganizer, PipSnapAlgorithm snapAlgorithm,
AccessibilityCallbacks callbacks, Runnable updateMovementBoundCallback,
- ShellExecutor mainExcutor) {
+ Runnable unstashCallback, ShellExecutor mainExcutor) {
mContext = context;
mMainExcutor = mainExcutor;
mPipBoundsState = pipBoundsState;
@@ -80,6 +83,7 @@
mTaskOrganizer = taskOrganizer;
mSnapAlgorithm = snapAlgorithm;
mUpdateMovementBoundCallback = updateMovementBoundCallback;
+ mUnstashCallback = unstashCallback;
mCallbacks = callbacks;
mConnectionImpl = new PipAccessibilityInteractionConnectionImpl();
}
@@ -118,6 +122,13 @@
setToNormalBounds();
}
result = true;
+ } else if (action == R.id.action_pip_stash) {
+ mMotionHelper.animateToStashedClosestEdge();
+ result = true;
+ } else if (action == R.id.action_pip_unstash) {
+ mUnstashCallback.run();
+ mPipBoundsState.setStashed(STASH_TYPE_NONE);
+ result = true;
} else {
switch (action) {
case AccessibilityNodeInfo.ACTION_CLICK:
@@ -246,6 +257,10 @@
info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_EXPAND);
info.addAction(new AccessibilityNodeInfo.AccessibilityAction(R.id.action_pip_resize,
context.getString(R.string.accessibility_action_pip_resize)));
+ info.addAction(new AccessibilityNodeInfo.AccessibilityAction(R.id.action_pip_stash,
+ context.getString(R.string.accessibility_action_pip_stash)));
+ info.addAction(new AccessibilityNodeInfo.AccessibilityAction(R.id.action_pip_unstash,
+ context.getString(R.string.accessibility_action_pip_unstash)));
info.setImportantForAccessibility(true);
info.setClickable(true);
info.setVisibleToUser(true);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
index 91e3887..4f3ec96 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
@@ -36,7 +36,6 @@
import android.graphics.Rect;
import android.os.IBinder;
import android.os.RemoteException;
-import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.Log;
@@ -44,6 +43,7 @@
import android.util.Size;
import android.util.Slog;
import android.view.DisplayInfo;
+import android.view.SurfaceControl;
import android.view.WindowManagerGlobal;
import android.window.WindowContainerTransaction;
@@ -51,6 +51,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.wm.shell.R;
import com.android.wm.shell.WindowManagerShellWrapper;
import com.android.wm.shell.common.DisplayChangeController;
@@ -168,7 +169,8 @@
}
};
- private final DisplayController.OnDisplaysChangedListener mDisplaysChangedListener =
+ @VisibleForTesting
+ final DisplayController.OnDisplaysChangedListener mDisplaysChangedListener =
new DisplayController.OnDisplaysChangedListener() {
@Override
public void onFixedRotationStarted(int displayId, int newRotation) {
@@ -450,7 +452,7 @@
null /* windowContainerTransaction */);
};
- if (saveRestoreSnapFraction) {
+ if (mPipTaskOrganizer.isInPip() && saveRestoreSnapFraction) {
// Calculate the snap fraction of the current stack along the old movement bounds
final PipSnapAlgorithm pipSnapAlgorithm = mPipBoundsAlgorithm.getSnapAlgorithm();
final Rect postChangeStackBounds = new Rect(mPipBoundsState.getBounds());
@@ -557,8 +559,9 @@
return entryBounds;
}
- private void stopSwipePipToHome(ComponentName componentName, Rect destinationBounds) {
- mPipTaskOrganizer.stopSwipePipToHome(componentName, destinationBounds);
+ private void stopSwipePipToHome(ComponentName componentName, Rect destinationBounds,
+ SurfaceControl overlay) {
+ mPipTaskOrganizer.stopSwipePipToHome(componentName, destinationBounds, overlay);
}
@Override
@@ -604,7 +607,6 @@
// Re-enable touches after the animation completes
mTouchHandler.setTouchEnabled(true);
mTouchHandler.onPinnedStackAnimationEnded(direction);
- mMenuController.onPinnedStackAnimationEnded();
}
private void updateMovementBounds(@Nullable Rect toBounds, boolean fromRotation,
@@ -850,10 +852,11 @@
}
@Override
- public void stopSwipePipToHome(ComponentName componentName, Rect destinationBounds) {
+ public void stopSwipePipToHome(ComponentName componentName, Rect destinationBounds,
+ SurfaceControl overlay) {
executeRemoteCallWithTaskPermission(mController, "stopSwipePipToHome",
(controller) -> {
- controller.stopSwipePipToHome(componentName, destinationBounds);
+ controller.stopSwipePipToHome(componentName, destinationBounds, overlay);
});
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java
index 7b17fe4..e210835 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java
@@ -40,7 +40,6 @@
import android.content.Intent;
import android.graphics.Color;
import android.graphics.Rect;
-import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
@@ -279,11 +278,17 @@
mMenuContainerAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
+ mAllowTouches = true;
notifyMenuStateChangeFinish(menuState);
if (allowMenuTimeout) {
repostDelayedHide(INITIAL_DISMISS_DELAY);
}
}
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ mAllowTouches = true;
+ }
});
if (withDelay) {
// starts the menu container animation after window expansion is completed
@@ -326,10 +331,6 @@
cancelDelayedHide();
}
- void onPipAnimationEnded() {
- mAllowTouches = true;
- }
-
void updateMenuLayout(Rect bounds) {
mPipMenuIconsAlgorithm.onBoundsChanged(bounds);
}
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 9401cd6..15e7f07 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
@@ -21,7 +21,9 @@
import static androidx.dynamicanimation.animation.SpringForce.STIFFNESS_MEDIUM;
import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_EXPAND_OR_UNEXPAND;
+import static com.android.wm.shell.pip.PipBoundsState.STASH_TYPE_LEFT;
import static com.android.wm.shell.pip.PipBoundsState.STASH_TYPE_NONE;
+import static com.android.wm.shell.pip.PipBoundsState.STASH_TYPE_RIGHT;
import static com.android.wm.shell.pip.phone.PipMenuView.ANIM_TYPE_DISMISS;
import static com.android.wm.shell.pip.phone.PipMenuView.ANIM_TYPE_NONE;
@@ -499,6 +501,28 @@
}
/**
+ * Animates the PiP to the stashed state, choosing the closest edge.
+ */
+ void animateToStashedClosestEdge() {
+ Rect tmpBounds = new Rect();
+ final Rect insetBounds = mPipBoundsState.getDisplayLayout().stableInsets();
+ final int stashType =
+ mPipBoundsState.getBounds().left == mPipBoundsState.getMovementBounds().left
+ ? STASH_TYPE_LEFT : STASH_TYPE_RIGHT;
+ final float leftEdge = stashType == STASH_TYPE_LEFT
+ ? mPipBoundsState.getStashOffset()
+ - mPipBoundsState.getBounds().width() + insetBounds.left
+ : mPipBoundsState.getDisplayBounds().right
+ - mPipBoundsState.getStashOffset() - insetBounds.right;
+ tmpBounds.set((int) leftEdge,
+ mPipBoundsState.getBounds().top,
+ (int) (leftEdge + mPipBoundsState.getBounds().width()),
+ mPipBoundsState.getBounds().bottom);
+ resizeAndAnimatePipUnchecked(tmpBounds, UNSTASH_DURATION);
+ mPipBoundsState.setStashed(stashType);
+ }
+
+ /**
* Animates the PiP from stashed state into un-stashed, popping it out from the edge.
*/
void animateToUnStashedBounds(Rect unstashedBounds) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipPinchResizingAlgorithm.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipPinchResizingAlgorithm.java
index f8125fd..23153be72 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipPinchResizingAlgorithm.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipPinchResizingAlgorithm.java
@@ -27,6 +27,7 @@
private static final int PINCH_RESIZE_MAX_ANGLE_ROTATION = 45;
private static final float OVERROTATE_DAMP_FACTOR = 0.4f;
private static final float ANGLE_THRESHOLD = 5f;
+ private static final float OVERRESIZE_DAMP_FACTOR = 0.25f;
private final PointF mTmpDownVector = new PointF();
private final PointF mTmpLastVector = new PointF();
@@ -46,7 +47,10 @@
lastSecondPoint.y - lastPoint.y);
float minScale = getMinScale(initialBounds, minSize);
float maxScale = getMaxScale(initialBounds, maxSize);
- float scale = Math.max(minScale, Math.min(maxScale, dist / downDist));
+ float overStretchMin = minScale - dist / downDist > 0 ? minScale - dist / downDist : 0;
+ float overStretchMax = dist / downDist - maxScale > 0 ? dist / downDist - maxScale : 0;
+ float scale = Math.max(minScale - overStretchMin * OVERRESIZE_DAMP_FACTOR,
+ Math.min(maxScale + overStretchMax * OVERRESIZE_DAMP_FACTOR, dist / downDist));
// Scale the bounds by the change in distance between the points
resizeBoundsOut.set(initialBounds);
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 0878f54..32553f9 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
@@ -383,14 +383,17 @@
return;
}
+ final Rect pipBounds = mPipBoundsState.getBounds();
if (action == MotionEvent.ACTION_POINTER_DOWN) {
- if (mFirstIndex == -1 && mSecondIndex == -1) {
+ if (mFirstIndex == -1 && mSecondIndex == -1
+ && pipBounds.contains((int) ev.getRawX(0), (int) ev.getRawY(0))
+ && pipBounds.contains((int) ev.getRawX(1), (int) ev.getRawY(1))) {
mAllowGesture = true;
mFirstIndex = 0;
mSecondIndex = 1;
mDownPoint.set(ev.getRawX(mFirstIndex), ev.getRawY(mFirstIndex));
mDownSecondPoint.set(ev.getRawX(mSecondIndex), ev.getRawY(mSecondIndex));
- mDownBounds.set(mPipBoundsState.getBounds());
+ mDownBounds.set(pipBounds);
mLastPoint.set(mDownPoint);
mLastSecondPoint.set(mLastSecondPoint);
@@ -514,7 +517,18 @@
|| mLastResizeBounds.height() >= PINCH_RESIZE_AUTO_MAX_RATIO * mMaxSize.y) {
resizeRectAboutCenter(mLastResizeBounds, mMaxSize.x, mMaxSize.y);
}
- final float snapFraction = mPipBoundsAlgorithm.getSnapFraction(mLastResizeBounds);
+ final int leftEdge = mLastResizeBounds.left;
+ final Rect movementBounds =
+ mPipBoundsAlgorithm.getMovementBounds(mLastResizeBounds);
+ final int fromLeft = Math.abs(leftEdge - movementBounds.left);
+ final int fromRight = Math.abs(movementBounds.right - leftEdge);
+ // The PIP will be snapped to either the right or left edge, so calculate which one
+ // is closest to the current position.
+ final int newLeft = fromLeft < fromRight
+ ? movementBounds.left : movementBounds.right;
+ mLastResizeBounds.offsetTo(newLeft, mLastResizeBounds.top);
+ final float snapFraction = mPipBoundsAlgorithm.getSnapFraction(
+ mLastResizeBounds, movementBounds);
mPipBoundsAlgorithm.applySnapFraction(mLastResizeBounds, snapFraction);
mPipTaskOrganizer.scheduleAnimateResizePip(startBounds, mLastResizeBounds,
PINCH_RESIZE_SNAP_DURATION, mAngle, callback);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
index 8f9dcef..304390d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
@@ -204,7 +204,8 @@
mainExecutor);
mConnection = new PipAccessibilityInteractionConnection(mContext, pipBoundsState,
mMotionHelper, pipTaskOrganizer, mPipBoundsAlgorithm.getSnapAlgorithm(),
- this::onAccessibilityShowMenu, this::updateMovementBounds, mainExecutor);
+ this::onAccessibilityShowMenu, this::updateMovementBounds,
+ this::animateToUnStashedState, mainExecutor);
}
public void init() {
@@ -472,17 +473,20 @@
float aspectRatio) {
final int shorterLength = Math.min(mPipBoundsState.getDisplayBounds().width(),
mPipBoundsState.getDisplayBounds().height());
- final int totalPadding = insetBounds.left * 2;
+ final int totalHorizontalPadding = insetBounds.left
+ + (mPipBoundsState.getDisplayBounds().width() - insetBounds.right);
+ final int totalVerticalPadding = insetBounds.top
+ + (mPipBoundsState.getDisplayBounds().height() - insetBounds.bottom);
final int minWidth, minHeight, maxWidth, maxHeight;
if (aspectRatio > 1f) {
minWidth = (int) Math.min(normalBounds.width(), shorterLength * MINIMUM_SIZE_PERCENT);
minHeight = (int) (minWidth / aspectRatio);
- maxWidth = (int) Math.max(normalBounds.width(), shorterLength - totalPadding);
+ maxWidth = (int) Math.max(normalBounds.width(), shorterLength - totalHorizontalPadding);
maxHeight = (int) (maxWidth / aspectRatio);
} else {
minHeight = (int) Math.min(normalBounds.height(), shorterLength * MINIMUM_SIZE_PERCENT);
minWidth = (int) (minHeight * aspectRatio);
- maxHeight = (int) Math.max(normalBounds.height(), shorterLength - totalPadding);
+ maxHeight = (int) Math.max(normalBounds.height(), shorterLength - totalVerticalPadding);
maxWidth = (int) (maxHeight * aspectRatio);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MainStage.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MainStage.java
index 66a4a60..d0998eb 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MainStage.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MainStage.java
@@ -19,6 +19,7 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import android.graphics.Rect;
+import android.view.SurfaceSession;
import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
@@ -36,8 +37,9 @@
private boolean mIsActive = false;
MainStage(ShellTaskOrganizer taskOrganizer, int displayId,
- StageListenerCallbacks callbacks, SyncTransactionQueue syncQueue) {
- super(taskOrganizer, displayId, callbacks, syncQueue);
+ StageListenerCallbacks callbacks, SyncTransactionQueue syncQueue,
+ SurfaceSession surfaceSession) {
+ super(taskOrganizer, displayId, callbacks, syncQueue, surfaceSession);
}
boolean isActive() {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java
index 01a81d2..82f95a4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java
@@ -18,6 +18,7 @@
import android.app.ActivityManager;
import android.graphics.Rect;
+import android.view.SurfaceSession;
import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
@@ -33,8 +34,9 @@
private static final String TAG = SideStage.class.getSimpleName();
SideStage(ShellTaskOrganizer taskOrganizer, int displayId,
- StageListenerCallbacks callbacks, SyncTransactionQueue syncQueue) {
- super(taskOrganizer, displayId, callbacks, syncQueue);
+ StageListenerCallbacks callbacks, SyncTransactionQueue syncQueue,
+ SurfaceSession surfaceSession) {
+ super(taskOrganizer, displayId, callbacks, syncQueue, surfaceSession);
}
void addTask(ActivityManager.RunningTaskInfo task, Rect rootBounds,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java
index d4506fd..002bfb6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java
@@ -19,6 +19,7 @@
import android.annotation.IntDef;
import com.android.wm.shell.common.annotations.ExternalThread;
+import com.android.wm.shell.common.split.SplitLayout.SplitPosition;
/**
* Interface to engage split-screen feature.
@@ -27,29 +28,6 @@
@ExternalThread
public interface SplitScreen {
/**
- * Stage position isn't specified normally meaning to use what ever it is currently set to.
- */
- int STAGE_POSITION_UNDEFINED = -1;
- /**
- * Specifies that a stage is positioned at the top half of the screen if
- * in portrait mode or at the left half of the screen if in landscape mode.
- */
- int STAGE_POSITION_TOP_OR_LEFT = 0;
-
- /**
- * Specifies that a stage is positioned at the bottom half of the screen if
- * in portrait mode or at the right half of the screen if in landscape mode.
- */
- int STAGE_POSITION_BOTTOM_OR_RIGHT = 1;
-
- @IntDef(prefix = { "STAGE_POSITION_" }, value = {
- STAGE_POSITION_UNDEFINED,
- STAGE_POSITION_TOP_OR_LEFT,
- STAGE_POSITION_BOTTOM_OR_RIGHT
- })
- @interface StagePosition {}
-
- /**
* Stage type isn't specified normally meaning to use what ever the default is.
* E.g. exit split-screen and launch the app in fullscreen.
*/
@@ -75,7 +53,7 @@
/** Callback interface for listening to changes in a split-screen stage. */
interface SplitScreenListener {
- void onStagePositionChanged(@StageType int stage, @StagePosition int position);
+ void onStagePositionChanged(@StageType int stage, @SplitPosition int position);
void onTaskStageChanged(int taskId, @StageType int stage, boolean visible);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
index 5aa59f2..9a457b5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
@@ -19,9 +19,9 @@
import static android.view.Display.DEFAULT_DISPLAY;
import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission;
-import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_POSITION_BOTTOM_OR_RIGHT;
-import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_POSITION_TOP_OR_LEFT;
-import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_POSITION_UNDEFINED;
+import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_BOTTOM_OR_RIGHT;
+import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_TOP_OR_LEFT;
+import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_UNDEFINED;
import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_MAIN;
import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_SIDE;
import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_UNDEFINED;
@@ -53,6 +53,7 @@
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.common.TransactionPool;
import com.android.wm.shell.common.annotations.ExternalThread;
+import com.android.wm.shell.common.split.SplitLayout.SplitPosition;
import com.android.wm.shell.draganddrop.DragAndDropPolicy;
import com.android.wm.shell.splitscreen.ISplitScreenListener;
import com.android.wm.shell.transition.Transitions;
@@ -122,7 +123,7 @@
return mStageCoordinator.isSplitScreenVisible();
}
- public boolean moveToSideStage(int taskId, @SplitScreen.StagePosition int sideStagePosition) {
+ public boolean moveToSideStage(int taskId, @SplitPosition int sideStagePosition) {
final ActivityManager.RunningTaskInfo task = mTaskOrganizer.getRunningTaskInfo(taskId);
if (task == null) {
throw new IllegalArgumentException("Unknown taskId" + taskId);
@@ -131,7 +132,7 @@
}
public boolean moveToSideStage(ActivityManager.RunningTaskInfo task,
- @SplitScreen.StagePosition int sideStagePosition) {
+ @SplitPosition int sideStagePosition) {
return mStageCoordinator.moveToSideStage(task, sideStagePosition);
}
@@ -139,7 +140,7 @@
return mStageCoordinator.removeFromSideStage(taskId);
}
- public void setSideStagePosition(@SplitScreen.StagePosition int sideStagePosition) {
+ public void setSideStagePosition(@SplitPosition int sideStagePosition) {
mStageCoordinator.setSideStagePosition(sideStagePosition);
}
@@ -149,7 +150,7 @@
public void enterSplitScreen(int taskId, boolean leftOrTop) {
moveToSideStage(taskId,
- leftOrTop ? STAGE_POSITION_TOP_OR_LEFT : STAGE_POSITION_BOTTOM_OR_RIGHT);
+ leftOrTop ? SPLIT_POSITION_TOP_OR_LEFT : SPLIT_POSITION_BOTTOM_OR_RIGHT);
}
public void exitSplitScreen() {
@@ -173,7 +174,7 @@
}
public void startTask(int taskId, @SplitScreen.StageType int stage,
- @SplitScreen.StagePosition int position, @Nullable Bundle options) {
+ @SplitPosition int position, @Nullable Bundle options) {
options = resolveStartStage(stage, position, options);
try {
@@ -184,7 +185,7 @@
}
public void startShortcut(String packageName, String shortcutId,
- @SplitScreen.StageType int stage, @SplitScreen.StagePosition int position,
+ @SplitScreen.StageType int stage, @SplitPosition int position,
@Nullable Bundle options, UserHandle user) {
options = resolveStartStage(stage, position, options);
@@ -199,7 +200,7 @@
}
public void startIntent(PendingIntent intent, Intent fillInIntent,
- @SplitScreen.StageType int stage, @SplitScreen.StagePosition int position,
+ @SplitScreen.StageType int stage, @SplitPosition int position,
@Nullable Bundle options) {
options = resolveStartStage(stage, position, options);
@@ -211,11 +212,11 @@
}
private Bundle resolveStartStage(@SplitScreen.StageType int stage,
- @SplitScreen.StagePosition int position, @Nullable Bundle options) {
+ @SplitPosition int position, @Nullable Bundle options) {
switch (stage) {
case STAGE_TYPE_UNDEFINED: {
// Use the stage of the specified position is valid.
- if (position != STAGE_POSITION_UNDEFINED) {
+ if (position != SPLIT_POSITION_UNDEFINED) {
if (position == mStageCoordinator.getSideStagePosition()) {
options = resolveStartStage(STAGE_TYPE_SIDE, position, options);
} else {
@@ -228,7 +229,7 @@
break;
}
case STAGE_TYPE_SIDE: {
- if (position != STAGE_POSITION_UNDEFINED) {
+ if (position != SPLIT_POSITION_UNDEFINED) {
mStageCoordinator.setSideStagePosition(position);
} else {
position = mStageCoordinator.getSideStagePosition();
@@ -240,10 +241,10 @@
break;
}
case STAGE_TYPE_MAIN: {
- if (position != STAGE_POSITION_UNDEFINED) {
+ if (position != SPLIT_POSITION_UNDEFINED) {
// Set the side stage opposite of what we want to the main stage.
- final int sideStagePosition = position == STAGE_POSITION_TOP_OR_LEFT
- ? STAGE_POSITION_BOTTOM_OR_RIGHT : STAGE_POSITION_TOP_OR_LEFT;
+ final int sideStagePosition = position == SPLIT_POSITION_TOP_OR_LEFT
+ ? SPLIT_POSITION_BOTTOM_OR_RIGHT : SPLIT_POSITION_TOP_OR_LEFT;
mStageCoordinator.setSideStagePosition(sideStagePosition);
} else {
position = mStageCoordinator.getMainStagePosition();
@@ -418,7 +419,7 @@
@Override
public void startTasks(int mainTaskId, @Nullable Bundle mainOptions,
int sideTaskId, @Nullable Bundle sideOptions,
- @SplitScreen.StagePosition int sidePosition,
+ @SplitPosition int sidePosition,
@Nullable IRemoteTransition remoteTransition) {
executeRemoteCallWithTaskPermission(mController, "startTasks",
(controller) -> controller.mStageCoordinator.startTasks(mainTaskId, mainOptions,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index 4be9e75..0264c5a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -25,8 +25,9 @@
import static android.view.WindowManager.TRANSIT_TO_FRONT;
import static android.view.WindowManager.transitTypeToString;
-import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_POSITION_BOTTOM_OR_RIGHT;
-import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_POSITION_TOP_OR_LEFT;
+import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_BOTTOM_OR_RIGHT;
+import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_TOP_OR_LEFT;
+import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_UNDEFINED;
import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_MAIN;
import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_SIDE;
import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_UNDEFINED;
@@ -47,14 +48,15 @@
import android.os.IBinder;
import android.util.Log;
import android.view.SurfaceControl;
+import android.view.SurfaceSession;
import android.view.WindowManager;
import android.window.DisplayAreaInfo;
import android.window.IRemoteTransition;
import android.window.TransitionInfo;
import android.window.TransitionRequestInfo;
+import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
-
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.common.ProtoLog;
@@ -64,6 +66,7 @@
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.common.TransactionPool;
import com.android.wm.shell.common.split.SplitLayout;
+import com.android.wm.shell.common.split.SplitLayout.SplitPosition;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.transition.Transitions;
@@ -84,19 +87,22 @@
* This rules are mostly implemented in {@link #onStageVisibilityChanged(StageListenerImpl)} and
* {@link #onStageHasChildrenChanged(StageListenerImpl).}
*/
-class StageCoordinator implements SplitLayout.LayoutChangeListener,
- RootTaskDisplayAreaOrganizer.RootTaskDisplayAreaListener, Transitions.TransitionHandler {
+class StageCoordinator implements SplitLayout.SplitLayoutHandler,
+ RootTaskDisplayAreaOrganizer.RootTaskDisplayAreaListener, Transitions.TransitionHandler {
private static final String TAG = StageCoordinator.class.getSimpleName();
/** internal value for mDismissTop that represents no dismiss */
private static final int NO_DISMISS = -2;
+ private final SurfaceSession mSurfaceSession = new SurfaceSession();
+
private final MainStage mMainStage;
private final StageListenerImpl mMainStageListener = new StageListenerImpl();
private final SideStage mSideStage;
private final StageListenerImpl mSideStageListener = new StageListenerImpl();
- private @SplitScreen.StagePosition int mSideStagePosition = STAGE_POSITION_BOTTOM_OR_RIGHT;
+ @SplitPosition
+ private int mSideStagePosition = SPLIT_POSITION_BOTTOM_OR_RIGHT;
private final int mDisplayId;
private SplitLayout mSplitLayout;
@@ -115,8 +121,8 @@
/** Whether the device is supporting legacy split or not. */
private boolean mUseLegacySplit;
-
@SplitScreen.StageType int mDismissTop = NO_DISMISS;
+
private final Runnable mOnTransitionAnimationComplete = () -> {
// If still playing, let it finish.
if (!isSplitScreenVisible()) {
@@ -137,8 +143,18 @@
mSyncQueue = syncQueue;
mRootTDAOrganizer = rootTDAOrganizer;
mTaskOrganizer = taskOrganizer;
- mMainStage = new MainStage(mTaskOrganizer, mDisplayId, mMainStageListener, mSyncQueue);
- mSideStage = new SideStage(mTaskOrganizer, mDisplayId, mSideStageListener, mSyncQueue);
+ mMainStage = new MainStage(
+ mTaskOrganizer,
+ mDisplayId,
+ mMainStageListener,
+ mSyncQueue,
+ mSurfaceSession);
+ mSideStage = new SideStage(
+ mTaskOrganizer,
+ mDisplayId,
+ mSideStageListener,
+ mSyncQueue,
+ mSurfaceSession);
mDisplayImeController = displayImeController;
mRootTDAOrganizer.registerListener(displayId, this);
mSplitTransitions = new SplitScreenTransitions(transactionPool, transitions,
@@ -176,7 +192,7 @@
}
boolean moveToSideStage(ActivityManager.RunningTaskInfo task,
- @SplitScreen.StagePosition int sideStagePosition) {
+ @SplitPosition int sideStagePosition) {
final WindowContainerTransaction wct = new WindowContainerTransaction();
setSideStagePosition(sideStagePosition);
mMainStage.activate(getMainStageBounds(), wct);
@@ -201,7 +217,7 @@
/** Starts 2 tasks in one transition. */
void startTasks(int mainTaskId, @Nullable Bundle mainOptions, int sideTaskId,
- @Nullable Bundle sideOptions, @SplitScreen.StagePosition int sidePosition,
+ @Nullable Bundle sideOptions, @SplitPosition int sidePosition,
@Nullable IRemoteTransition remoteTransition) {
final WindowContainerTransaction wct = new WindowContainerTransaction();
mainOptions = mainOptions != null ? mainOptions : new Bundle();
@@ -225,20 +241,22 @@
TRANSIT_SPLIT_SCREEN_PAIR_OPEN, wct, remoteTransition, this);
}
- @SplitScreen.StagePosition int getSideStagePosition() {
+ @SplitLayout.SplitPosition
+ int getSideStagePosition() {
return mSideStagePosition;
}
- @SplitScreen.StagePosition int getMainStagePosition() {
- return mSideStagePosition == STAGE_POSITION_TOP_OR_LEFT
- ? STAGE_POSITION_BOTTOM_OR_RIGHT : STAGE_POSITION_TOP_OR_LEFT;
+ @SplitLayout.SplitPosition
+ int getMainStagePosition() {
+ return mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT
+ ? SPLIT_POSITION_BOTTOM_OR_RIGHT : SPLIT_POSITION_TOP_OR_LEFT;
}
- void setSideStagePosition(@SplitScreen.StagePosition int sideStagePosition) {
+ void setSideStagePosition(@SplitPosition int sideStagePosition) {
setSideStagePosition(sideStagePosition, true /* updateVisibility */);
}
- private void setSideStagePosition(@SplitScreen.StagePosition int sideStagePosition,
+ private void setSideStagePosition(@SplitPosition int sideStagePosition,
boolean updateVisibility) {
if (mSideStagePosition == sideStagePosition) return;
mSideStagePosition = sideStagePosition;
@@ -289,7 +307,7 @@
opts.putParcelable(KEY_LAUNCH_ROOT_TASK_TOKEN, stage.mRootTaskInfo.token);
}
- void updateActivityOptions(Bundle opts, @SplitScreen.StagePosition int position) {
+ void updateActivityOptions(Bundle opts, @SplitPosition int position) {
addActivityOptions(opts, position == mSideStagePosition ? mSideStage : mMainStage);
if (!mMainStage.isActive()) {
@@ -487,8 +505,8 @@
@Override
public void onSnappedToDismiss(boolean bottomOrRight) {
final boolean mainStageToTop =
- bottomOrRight ? mSideStagePosition == STAGE_POSITION_BOTTOM_OR_RIGHT
- : mSideStagePosition == STAGE_POSITION_TOP_OR_LEFT;
+ bottomOrRight ? mSideStagePosition == SPLIT_POSITION_BOTTOM_OR_RIGHT
+ : mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT;
if (ENABLE_SHELL_TRANSITIONS) {
onSnappedToDismissTransition(mainStageToTop);
return;
@@ -497,55 +515,49 @@
}
@Override
- public void onBoundsChanging(SplitLayout layout) {
- final SurfaceControl dividerLeash = mSplitLayout.getDividerLeash();
- if (dividerLeash == null) return;
- final Rect mainStageBounds = getMainStageBounds();
- final Rect sideStageBounds = getSideStageBounds();
-
- mSyncQueue.runInSync(t -> t
- .setPosition(dividerLeash,
- mSplitLayout.getDividerBounds().left, mSplitLayout.getDividerBounds().top)
- .setPosition(mMainStage.mRootLeash, mainStageBounds.left, mainStageBounds.top)
- .setPosition(mSideStage.mRootLeash, sideStageBounds.left, sideStageBounds.top)
- // Sets crop to prevent visible region of tasks overlap with each other when
- // re-positioning surfaces while resizing.
- .setWindowCrop(mMainStage.mRootLeash,
- mainStageBounds.width(), mainStageBounds.height())
- .setWindowCrop(mSideStage.mRootLeash,
- sideStageBounds.width(), sideStageBounds.height()));
-
+ public void onDoubleTappedDivider() {
+ setSideStagePosition(mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT
+ ? SPLIT_POSITION_BOTTOM_OR_RIGHT : SPLIT_POSITION_TOP_OR_LEFT);
}
@Override
- public void onDoubleTappedDivider() {
- setSideStagePosition(mSideStagePosition == STAGE_POSITION_TOP_OR_LEFT
- ? STAGE_POSITION_BOTTOM_OR_RIGHT : STAGE_POSITION_TOP_OR_LEFT);
+ public void onBoundsChanging(SplitLayout layout) {
+ final StageTaskListener topLeftStage =
+ mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT ? mSideStage : mMainStage;
+ final StageTaskListener bottomRightStage =
+ mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT ? mMainStage : mSideStage;
+
+ mSyncQueue.runInSync(t -> layout.applySurfaceChanges(t, topLeftStage.mRootLeash,
+ bottomRightStage.mRootLeash, topLeftStage.mDimLayer, bottomRightStage.mDimLayer));
}
@Override
public void onBoundsChanged(SplitLayout layout) {
- final SurfaceControl dividerLeash = mSplitLayout.getDividerLeash();
- if (dividerLeash == null) return;
- final Rect mainStageBounds = getMainStageBounds();
- final Rect sideStageBounds = getSideStageBounds();
- final WindowContainerTransaction wct = new WindowContainerTransaction();
- mMainStage.setBounds(mainStageBounds, wct);
- mSideStage.setBounds(sideStageBounds, wct);
- mTaskOrganizer.applyTransaction(wct);
+ final StageTaskListener topLeftStage =
+ mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT ? mSideStage : mMainStage;
+ final StageTaskListener bottomRightStage =
+ mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT ? mMainStage : mSideStage;
- mSyncQueue.runInSync(t -> t
- // Resets layer of divider bar to make sure it is always on top.
- .setLayer(dividerLeash, Integer.MAX_VALUE)
- .setPosition(dividerLeash,
- mSplitLayout.getDividerBounds().left, mSplitLayout.getDividerBounds().top)
- .setPosition(mMainStage.mRootLeash,
- mainStageBounds.left, mainStageBounds.top)
- .setPosition(mSideStage.mRootLeash,
- sideStageBounds.left, sideStageBounds.top)
- // Resets crop to apply new surface bounds directly.
- .setWindowCrop(mMainStage.mRootLeash, null)
- .setWindowCrop(mSideStage.mRootLeash, null));
+ final WindowContainerTransaction wct = new WindowContainerTransaction();
+ layout.applyTaskChanges(wct, topLeftStage.mRootTaskInfo, bottomRightStage.mRootTaskInfo);
+ mSyncQueue.queue(wct);
+ mSyncQueue.runInSync(t -> layout.applySurfaceChanges(t, topLeftStage.mRootLeash,
+ bottomRightStage.mRootLeash, topLeftStage.mDimLayer, bottomRightStage.mDimLayer));
+ }
+
+ @Override
+ public int getSplitItemPosition(WindowContainerToken token) {
+ if (token == null) {
+ return SPLIT_POSITION_UNDEFINED;
+ }
+
+ if (token.equals(mMainStage.mRootTaskInfo.getToken())) {
+ return getMainStagePosition();
+ } else if (token.equals(mSideStage.mRootTaskInfo.getToken())) {
+ return getSideStagePosition();
+ }
+
+ return SPLIT_POSITION_UNDEFINED;
}
@Override
@@ -555,7 +567,7 @@
mSplitLayout = new SplitLayout(TAG + "SplitDivider", mContext,
mDisplayAreaInfo.configuration, this,
b -> mRootTDAOrganizer.attachToDisplayArea(mDisplayId, b),
- mDisplayImeController);
+ mDisplayImeController, mTaskOrganizer);
}
}
@@ -574,12 +586,12 @@
}
private Rect getSideStageBounds() {
- return mSideStagePosition == STAGE_POSITION_TOP_OR_LEFT
+ return mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT
? mSplitLayout.getBounds1() : mSplitLayout.getBounds2();
}
private Rect getMainStageBounds() {
- return mSideStagePosition == STAGE_POSITION_TOP_OR_LEFT
+ return mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT
? mSplitLayout.getBounds2() : mSplitLayout.getBounds1();
}
@@ -742,7 +754,7 @@
// Update local states (before animating).
setDividerVisibility(true);
- setSideStagePosition(STAGE_POSITION_BOTTOM_OR_RIGHT, false /* updateVisibility */);
+ setSideStagePosition(SPLIT_POSITION_BOTTOM_OR_RIGHT, false /* updateVisibility */);
setSplitsVisible(true);
addDividerBarToTransition(info, t, true /* show */);
@@ -908,6 +920,13 @@
StageCoordinator.this.onStageRootTaskVanished(this);
}
+ @Override
+ public void onNoLongerSupportMultiWindow() {
+ if (mMainStage.isActive()) {
+ StageCoordinator.this.exitSplitScreen();
+ }
+ }
+
private void reset() {
mHasRootTask = false;
mVisible = false;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
index 1da0a2d..0fd8eca62 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
@@ -29,11 +29,13 @@
import android.graphics.Rect;
import android.util.SparseArray;
import android.view.SurfaceControl;
+import android.view.SurfaceSession;
import android.window.WindowContainerTransaction;
import androidx.annotation.NonNull;
import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.common.SurfaceUtils;
import com.android.wm.shell.common.SyncTransactionQueue;
import java.io.PrintWriter;
@@ -44,6 +46,7 @@
* They only serve to hold a collection of tasks and provide APIs like
* {@link #setBounds(Rect, WindowContainerTransaction)} for the centralized {@link StageCoordinator}
* to perform operations in-sync with other containers.
+ *
* @see StageCoordinator
*/
class StageTaskListener implements ShellTaskOrganizer.TaskListener {
@@ -58,22 +61,31 @@
/** Callback interface for listening to changes in a split-screen stage. */
public interface StageListenerCallbacks {
void onRootTaskAppeared();
+
void onStatusChanged(boolean visible, boolean hasChildren);
+
void onChildTaskStatusChanged(int taskId, boolean present, boolean visible);
+
void onRootTaskVanished();
+ void onNoLongerSupportMultiWindow();
}
+
private final StageListenerCallbacks mCallbacks;
private final SyncTransactionQueue mSyncQueue;
+ private final SurfaceSession mSurfaceSession;
protected ActivityManager.RunningTaskInfo mRootTaskInfo;
protected SurfaceControl mRootLeash;
+ protected SurfaceControl mDimLayer;
protected SparseArray<ActivityManager.RunningTaskInfo> mChildrenTaskInfo = new SparseArray<>();
private final SparseArray<SurfaceControl> mChildrenLeashes = new SparseArray<>();
StageTaskListener(ShellTaskOrganizer taskOrganizer, int displayId,
- StageListenerCallbacks callbacks, SyncTransactionQueue syncQueue) {
+ StageListenerCallbacks callbacks, SyncTransactionQueue syncQueue,
+ SurfaceSession surfaceSession) {
mCallbacks = callbacks;
mSyncQueue = syncQueue;
+ mSurfaceSession = surfaceSession;
taskOrganizer.createRootTask(displayId, WINDOWING_MODE_MULTI_WINDOW, this);
}
@@ -93,6 +105,8 @@
mRootTaskInfo = taskInfo;
mCallbacks.onRootTaskAppeared();
sendStatusChanged();
+ mSyncQueue.runInSync(t -> mDimLayer =
+ SurfaceUtils.makeDimLayer(t, mRootLeash, "Dim layer", mSurfaceSession));
} else if (taskInfo.parentTaskId == mRootTaskInfo.taskId) {
final int taskId = taskInfo.taskId;
mChildrenLeashes.put(taskId, leash);
@@ -113,6 +127,11 @@
@Override
@CallSuper
public void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo) {
+ if (!taskInfo.supportsMultiWindow) {
+ // Leave split screen if the task no longer supports multi window.
+ mCallbacks.onNoLongerSupportMultiWindow();
+ return;
+ }
if (mRootTaskInfo.taskId == taskInfo.taskId) {
mRootTaskInfo = taskInfo;
} else if (taskInfo.parentTaskId == mRootTaskInfo.taskId) {
@@ -140,6 +159,7 @@
final int taskId = taskInfo.taskId;
if (mRootTaskInfo.taskId == taskId) {
mCallbacks.onRootTaskVanished();
+ mSyncQueue.runInSync(t -> t.remove(mDimLayer));
mRootTaskInfo = null;
} else if (mChildrenTaskInfo.contains(taskId)) {
mChildrenTaskInfo.remove(taskId);
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 1f098c2..a646231 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
@@ -39,6 +39,7 @@
import android.os.Trace;
import android.util.Slog;
import android.view.SurfaceControl;
+import android.view.View;
import android.window.SplashScreenView;
import com.android.internal.R;
@@ -308,7 +309,7 @@
mFinalIconDrawable = SplashscreenIconDrawableFactory.makeIconDrawable(
mTmpAttrs.mIconBgColor != Color.TRANSPARENT
? mTmpAttrs.mIconBgColor : mThemeColor,
- iconDrawable, mFinalIconSize, mSplashscreenWorkerHandler);
+ iconDrawable, mDefaultIconSize, mFinalIconSize, mSplashscreenWorkerHandler);
}
private boolean processAdaptiveIcon(Drawable iconDrawable) {
@@ -398,7 +399,17 @@
splashScreenView.setNotCopyable();
splashScreenView.setRevealAnimationSupported(false);
}
- splashScreenView.makeSystemUIColorsTransparent();
+ splashScreenView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
+ @Override
+ public void onViewAttachedToWindow(View v) {
+ SplashScreenView.applySystemBarsContrastColor(v.getWindowInsetsController(),
+ splashScreenView.getInitBackgroundColor());
+ }
+
+ @Override
+ public void onViewDetachedFromWindow(View v) {
+ }
+ });
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
return splashScreenView;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenIconDrawableFactory.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenIconDrawableFactory.java
index 6cbba9f..e8d95ab 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenIconDrawableFactory.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenIconDrawableFactory.java
@@ -24,7 +24,6 @@
import android.annotation.NonNull;
import android.content.res.Resources;
import android.graphics.Bitmap;
-import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Matrix;
@@ -32,7 +31,6 @@
import android.graphics.Path;
import android.graphics.PixelFormat;
import android.graphics.Rect;
-import android.graphics.Shader;
import android.graphics.drawable.AdaptiveIconDrawable;
import android.graphics.drawable.Animatable;
import android.graphics.drawable.ColorDrawable;
@@ -51,59 +49,53 @@
public class SplashscreenIconDrawableFactory {
static Drawable makeIconDrawable(@ColorInt int backgroundColor,
- @NonNull Drawable foregroundDrawable, int iconSize,
+ @NonNull Drawable foregroundDrawable, int srcIconSize, int iconSize,
Handler splashscreenWorkerHandler) {
if (foregroundDrawable instanceof Animatable) {
return new AnimatableIconDrawable(backgroundColor, foregroundDrawable);
} else if (foregroundDrawable instanceof AdaptiveIconDrawable) {
- return new ImmobileIconDrawable((AdaptiveIconDrawable) foregroundDrawable, iconSize,
- splashscreenWorkerHandler);
+ return new ImmobileIconDrawable((AdaptiveIconDrawable) foregroundDrawable,
+ srcIconSize, iconSize, splashscreenWorkerHandler);
} else {
// TODO for legacy icon don't use adaptive icon drawable to wrapper it
return new ImmobileIconDrawable(new AdaptiveIconDrawable(
- new ColorDrawable(backgroundColor), foregroundDrawable), iconSize,
- splashscreenWorkerHandler);
+ new ColorDrawable(backgroundColor), foregroundDrawable),
+ srcIconSize, iconSize, splashscreenWorkerHandler);
}
}
private static class ImmobileIconDrawable extends Drawable {
- private boolean mCacheComplete;
private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG
| Paint.FILTER_BITMAP_FLAG);
+ private final Matrix mMatrix = new Matrix();
+ private Bitmap mIconBitmap;
- ImmobileIconDrawable(AdaptiveIconDrawable drawable, int iconSize,
+ ImmobileIconDrawable(AdaptiveIconDrawable drawable, int srcIconSize, int iconSize,
Handler splashscreenWorkerHandler) {
- splashscreenWorkerHandler.post(() -> cachePaint(drawable, iconSize, iconSize));
+ final float scale = (float) iconSize / srcIconSize;
+ mMatrix.setScale(scale, scale);
+ splashscreenWorkerHandler.post(() -> preDrawIcon(drawable, srcIconSize));
}
- private void cachePaint(AdaptiveIconDrawable drawable, int width, int height) {
+ private void preDrawIcon(AdaptiveIconDrawable drawable, int size) {
synchronized (mPaint) {
- if (mCacheComplete) {
- return;
- }
- Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "cachePaint");
- final Bitmap layersBitmap = Bitmap.createBitmap(width, height,
- Bitmap.Config.ARGB_8888);
- final Canvas canvas = new Canvas(layersBitmap);
- drawable.setBounds(0, 0, width, height);
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "preDrawIcon");
+ mIconBitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
+ final Canvas canvas = new Canvas(mIconBitmap);
+ drawable.setBounds(0, 0, size, size);
drawable.draw(canvas);
- final Shader layersShader = new BitmapShader(layersBitmap, Shader.TileMode.CLAMP,
- Shader.TileMode.CLAMP);
- mPaint.setShader(layersShader);
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
- mCacheComplete = true;
}
}
@Override
public void draw(Canvas canvas) {
synchronized (mPaint) {
- if (mCacheComplete) {
- final Rect bounds = getBounds();
- canvas.drawRect(bounds, mPaint);
+ if (mIconBitmap != null) {
+ canvas.drawBitmap(mIconBitmap, mMatrix, mPaint);
} else {
// this shouldn't happen, but if it really happen, invalidate self to wait
- // for cachePaint finish.
+ // for bitmap to be ready.
invalidateSelf();
}
}
@@ -111,12 +103,10 @@
@Override
public void setAlpha(int alpha) {
-
}
@Override
public void setColorFilter(ColorFilter colorFilter) {
-
}
@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 26e8753..187e104 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
@@ -25,12 +25,10 @@
import android.app.ActivityTaskManager;
import android.content.Context;
import android.content.pm.ActivityInfo;
-import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
-import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.hardware.display.DisplayManager;
import android.os.IBinder;
@@ -43,13 +41,13 @@
import android.view.SurfaceControl;
import android.view.View;
import android.view.WindowManager;
+import android.widget.FrameLayout;
import android.window.SplashScreenView;
import android.window.SplashScreenView.SplashScreenViewParcelable;
import android.window.StartingWindowInfo;
import android.window.TaskSnapshot;
import com.android.internal.R;
-import com.android.internal.policy.PhoneWindow;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.TransactionPool;
@@ -152,14 +150,6 @@
return;
}
- CharSequence nonLocalizedLabel = activityInfo.nonLocalizedLabel;
- int labelRes = activityInfo.labelRes;
- if (activityInfo.nonLocalizedLabel == null && activityInfo.labelRes == 0) {
- ApplicationInfo app = activityInfo.applicationInfo;
- nonLocalizedLabel = app.nonLocalizedLabel;
- labelRes = app.labelRes;
- }
-
final int taskId = taskInfo.taskId;
Context context = mContext;
// replace with the default theme if the application didn't set
@@ -169,8 +159,7 @@
: com.android.internal.R.style.Theme_DeviceDefault_DayNight;
if (DEBUG_SPLASH_SCREEN) {
Slog.d(TAG, "addSplashScreen " + activityInfo.packageName
- + ": nonLocalizedLabel=" + nonLocalizedLabel + " theme="
- + Integer.toHexString(theme) + " task= " + taskInfo.taskId);
+ + " theme=" + Integer.toHexString(theme) + " task= " + taskInfo.taskId);
}
// Obtain proper context to launch on the right display.
@@ -180,7 +169,7 @@
return;
}
context = displayContext;
- if (theme != context.getThemeResId() || labelRes != 0) {
+ if (theme != context.getThemeResId()) {
try {
context = context.createPackageContextAsUser(activityInfo.packageName,
CONTEXT_RESTRICTED, UserHandle.of(taskInfo.userId));
@@ -222,23 +211,22 @@
typedArray.recycle();
}
- final PhoneWindow win = new PhoneWindow(context);
- win.setIsStartingWindow(true);
-
- final Resources res = context.getResources();
- final CharSequence label = res.getText(labelRes, null);
- // Only change the accessibility title if the label is localized
- if (label != null) {
- win.setTitle(label, true);
- } else {
- win.setTitle(nonLocalizedLabel, false);
- }
-
- int windowFlags = WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
+ final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
+ WindowManager.LayoutParams.TYPE_APPLICATION_STARTING);
+ params.setFitInsetsSides(0);
+ params.setFitInsetsTypes(0);
+ int windowFlags = WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED
+ | WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
+ | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+ | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
final TypedArray a = context.obtainStyledAttributes(R.styleable.Window);
if (a.getBoolean(R.styleable.Window_windowShowWallpaper, false)) {
windowFlags |= WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
}
+ params.layoutInDisplayCutoutMode = a.getInt(
+ R.styleable.Window_windowLayoutInDisplayCutoutMode,
+ params.layoutInDisplayCutoutMode);
+ params.windowAnimations = a.getResourceId(R.styleable.Window_windowAnimationStyle, 0);
a.recycle();
// Assumes it's safe to show starting windows of launched apps while
@@ -256,28 +244,15 @@
windowFlags |= WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
- win.setFlags(windowFlags, windowFlags);
-
- final int iconRes = activityInfo.getIconResource();
- final int logoRes = activityInfo.getLogoResource();
- win.setDefaultIcon(iconRes);
- win.setDefaultLogo(logoRes);
-
- final WindowManager.LayoutParams params = win.getAttributes();
- params.type = WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
- params.width = WindowManager.LayoutParams.MATCH_PARENT;
- params.height = WindowManager.LayoutParams.MATCH_PARENT;
+ params.flags = windowFlags;
params.token = appToken;
params.packageName = activityInfo.packageName;
- params.windowAnimations = win.getWindowStyle().getResourceId(
- com.android.internal.R.styleable.Window_windowAnimationStyle, 0);
params.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
// Setting as trusted overlay to let touches pass through. This is safe because this
// window is controlled by the system.
params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;
- params.format = PixelFormat.RGBA_8888;
- if (!res.getCompatibilityInfo().supportsScreen()) {
+ if (!context.getResources().getCompatibilityInfo().supportsScreen()) {
params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
}
@@ -297,6 +272,7 @@
// Record whether create splash screen view success, notify to current thread after
// create splash screen view finished.
final SplashScreenViewSupplier viewSupplier = new SplashScreenViewSupplier();
+ final FrameLayout rootLayout = new FrameLayout(context);
final Runnable setViewSynchronized = () -> {
// waiting for setContentView before relayoutWindow
SplashScreenView contentView = viewSupplier.get();
@@ -306,8 +282,7 @@
// if view == null then creation of content view was failed.
if (contentView != null) {
try {
- win.setContentView(contentView);
- contentView.cacheRootWindow(win);
+ rootLayout.addView(contentView);
} catch (RuntimeException e) {
Slog.w(TAG, "failed set content view to starting window "
+ "at taskId: " + taskId, e);
@@ -321,9 +296,8 @@
viewSupplier::setView);
try {
- final View view = win.getDecorView();
final WindowManager wm = context.getSystemService(WindowManager.class);
- postAddWindow(taskId, appToken, view, wm, params);
+ postAddWindow(taskId, appToken, rootLayout, wm, params);
// We use the splash screen worker thread to create SplashScreenView while adding the
// window, as otherwise Choreographer#doFrame might be delayed on this thread.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
index b468462..8147b47 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
@@ -16,7 +16,6 @@
package com.android.wm.shell.startingsurface;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.graphics.Color.WHITE;
import static android.graphics.Color.alpha;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
@@ -63,7 +62,6 @@
import android.hardware.HardwareBuffer;
import android.os.IBinder;
import android.os.RemoteException;
-import android.os.SystemClock;
import android.os.Trace;
import android.util.MergedConfiguration;
import android.util.Slog;
@@ -94,9 +92,6 @@
* @hide
*/
public class TaskSnapshotWindow {
-
- private static final long SIZE_MISMATCH_MINIMUM_TIME_MS = 450;
-
/**
* When creating the starting window, we use the exact same layout flags such that we end up
* with a window with the exact same dimensions etc. However, these flags are not used in layout
@@ -136,10 +131,8 @@
private final RectF mTmpDstFrame = new RectF();
private final CharSequence mTitle;
private boolean mHasDrawn;
- private long mShownTime;
private boolean mSizeMismatch;
private final Paint mBackgroundPaint = new Paint();
- private final int mActivityType;
private final int mStatusBarColor;
private final SystemBarBackgroundPainter mSystemBarBackgroundPainter;
private final int mOrientationOnCreation;
@@ -195,8 +188,6 @@
final Point taskSize = snapshot.getTaskSize();
final Rect taskBounds = new Rect(0, 0, taskSize.x, taskSize.y);
final int orientation = snapshot.getOrientation();
-
- final int activityType = runningTaskInfo.topActivityType;
final int displayId = runningTaskInfo.displayId;
final IWindowSession session = WindowManagerGlobal.getWindowSession();
@@ -216,7 +207,7 @@
final TaskSnapshotWindow snapshotSurface = new TaskSnapshotWindow(
surfaceControl, snapshot, layoutParams.getTitle(), taskDescription, appearance,
- windowFlags, windowPrivateFlags, taskBounds, orientation, activityType,
+ windowFlags, windowPrivateFlags, taskBounds, orientation,
topWindowInsetsState, clearWindowHandler, mainExecutor);
final Window window = snapshotSurface.mWindow;
@@ -256,8 +247,8 @@
public TaskSnapshotWindow(SurfaceControl surfaceControl,
TaskSnapshot snapshot, CharSequence title, TaskDescription taskDescription,
int appearance, int windowFlags, int windowPrivateFlags, Rect taskBounds,
- int currentOrientation, int activityType, InsetsState topWindowInsetsState,
- Runnable clearWindowHandler, ShellExecutor splashScreenExecutor) {
+ int currentOrientation, InsetsState topWindowInsetsState, Runnable clearWindowHandler,
+ ShellExecutor splashScreenExecutor) {
mSplashScreenExecutor = splashScreenExecutor;
mSession = WindowManagerGlobal.getWindowSession();
mWindow = new Window();
@@ -272,7 +263,6 @@
windowPrivateFlags, appearance, taskDescription, 1f, topWindowInsetsState);
mStatusBarColor = taskDescription.getStatusBarColor();
mOrientationOnCreation = currentOrientation;
- mActivityType = activityType;
mTransaction = new SurfaceControl.Transaction();
mClearWindowHandler = clearWindowHandler;
}
@@ -295,17 +285,6 @@
}
void remove() {
- final long now = SystemClock.uptimeMillis();
- if (mSizeMismatch && now - mShownTime < SIZE_MISMATCH_MINIMUM_TIME_MS
- // Show the latest content as soon as possible for unlocking to home.
- && mActivityType != ACTIVITY_TYPE_HOME) {
- final long delayTime = mShownTime + SIZE_MISMATCH_MINIMUM_TIME_MS - now;
- mSplashScreenExecutor.executeDelayed(() -> remove(), delayTime);
- if (DEBUG) {
- Slog.d(TAG, "Defer removing snapshot surface in " + delayTime);
- }
- return;
- }
try {
if (DEBUG) {
Slog.d(TAG, "Removing snapshot surface, mHasDrawn: " + mHasDrawn);
@@ -346,7 +325,6 @@
} else {
drawSizeMatchSnapshot();
}
- mShownTime = SystemClock.uptimeMillis();
mHasDrawn = true;
reportDrawn();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
index 3251abc..60707cc 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
@@ -22,6 +22,7 @@
import static android.view.WindowManager.TRANSIT_OPEN;
import static android.view.WindowManager.TRANSIT_TO_BACK;
import static android.view.WindowManager.TRANSIT_TO_FRONT;
+import static android.window.TransitionInfo.FLAG_IS_WALLPAPER;
import static android.window.TransitionInfo.FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT;
import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission;
@@ -226,18 +227,11 @@
}
/**
- * Reparents all participants into a shared parent and orders them based on: the global transit
- * type, their transit mode, and their destination z-order.
+ * Sets up visibility/alpha/transforms to resemble the starting state of an animation.
*/
private static void setupStartState(@NonNull TransitionInfo info,
@NonNull SurfaceControl.Transaction t, @NonNull SurfaceControl.Transaction finishT) {
boolean isOpening = isOpeningType(info.getType());
- if (info.getRootLeash().isValid()) {
- t.show(info.getRootLeash());
- }
- // Put animating stuff above this line and put static stuff below it.
- int zSplitLine = info.getChanges().size();
- // changes should be ordered top-to-bottom in z
for (int i = info.getChanges().size() - 1; i >= 0; --i) {
final TransitionInfo.Change change = info.getChanges().get(i);
final SurfaceControl leash = change.getLeash();
@@ -254,6 +248,52 @@
continue;
}
+ if (mode == TRANSIT_OPEN || mode == TRANSIT_TO_FRONT) {
+ t.show(leash);
+ t.setMatrix(leash, 1, 0, 0, 1);
+ if (isOpening
+ // If this is a transferred starting window, we want it immediately visible.
+ && (change.getFlags() & FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT) == 0) {
+ t.setAlpha(leash, 0.f);
+ // fix alpha in finish transaction in case the animator itself no-ops.
+ finishT.setAlpha(leash, 1.f);
+ }
+ } else if (mode == TRANSIT_CLOSE || mode == TRANSIT_TO_BACK) {
+ // Wallpaper is a bit of an anomaly: it's visibility is tied to other WindowStates.
+ // As a result, we actually can't hide it's WindowToken because there may not be a
+ // transition associated with it becoming visible again. Fortunately, since it is
+ // always z-ordered to the back, we don't have to worry about it flickering to the
+ // front during reparenting, so the hide here isn't necessary for it.
+ if ((change.getFlags() & FLAG_IS_WALLPAPER) == 0) {
+ finishT.hide(leash);
+ }
+ }
+ }
+ }
+
+ /**
+ * Reparents all participants into a shared parent and orders them based on: the global transit
+ * type, their transit mode, and their destination z-order.
+ */
+ private static void setupAnimHierarchy(@NonNull TransitionInfo info,
+ @NonNull SurfaceControl.Transaction t, @NonNull SurfaceControl.Transaction finishT) {
+ boolean isOpening = isOpeningType(info.getType());
+ if (info.getRootLeash().isValid()) {
+ t.show(info.getRootLeash());
+ }
+ // Put animating stuff above this line and put static stuff below it.
+ int zSplitLine = info.getChanges().size();
+ // changes should be ordered top-to-bottom in z
+ for (int i = info.getChanges().size() - 1; i >= 0; --i) {
+ final TransitionInfo.Change change = info.getChanges().get(i);
+ final SurfaceControl leash = change.getLeash();
+ final int mode = info.getChanges().get(i).getMode();
+
+ // Don't reparent anything that isn't independent within its parents
+ if (!TransitionInfo.isIndependent(change, info)) {
+ continue;
+ }
+
boolean hasParent = change.getParent() != null;
if (!hasParent) {
@@ -263,24 +303,12 @@
}
// Put all the OPEN/SHOW on top
if (mode == TRANSIT_OPEN || mode == TRANSIT_TO_FRONT) {
- t.show(leash);
- t.setMatrix(leash, 1, 0, 0, 1);
if (isOpening) {
- // put on top with 0 alpha
+ // put on top
t.setLayer(leash, zSplitLine + info.getChanges().size() - i);
- if ((change.getFlags() & FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT) != 0) {
- // This received a transferred starting window, so make it immediately
- // visible.
- t.setAlpha(leash, 1.f);
- } else {
- t.setAlpha(leash, 0.f);
- // fix alpha in finish transaction in case the animator itself no-ops.
- finishT.setAlpha(leash, 1.f);
- }
} else {
- // put on bottom and leave it visible
+ // put on bottom
t.setLayer(leash, zSplitLine - i);
- t.setAlpha(leash, 1.f);
}
} else if (mode == TRANSIT_CLOSE || mode == TRANSIT_TO_BACK) {
if (isOpening) {
@@ -290,7 +318,7 @@
// put on top
t.setLayer(leash, zSplitLine + info.getChanges().size() - i);
}
- } else { // CHANGE
+ } else { // CHANGE or other
t.setLayer(leash, zSplitLine + info.getChanges().size() - i);
}
}
@@ -329,6 +357,8 @@
active.mInfo = info;
active.mStartT = t;
active.mFinishT = finishT;
+ setupStartState(active.mInfo, active.mStartT, active.mFinishT);
+
if (activeIdx > 0) {
// This is now playing at the same time as an existing animation, so try merging it.
attemptMergeTransition(mActiveTransitions.get(0), active);
@@ -357,7 +387,7 @@
}
void playTransition(@NonNull ActiveTransition active) {
- setupStartState(active.mInfo, active.mStartT, active.mFinishT);
+ setupAnimHierarchy(active.mInfo, active.mStartT, active.mFinishT);
// If a handler already chose to run this animation, try delegating to it first.
if (active.mHandler != null) {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
index fcd333f..c5b5b91 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
@@ -115,23 +115,20 @@
val displayBounds = WindowUtils.getDisplayBounds(rotation)
return if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) {
Region(0, 0, displayBounds.bounds.right,
- dividerRegion.bounds.bottom - WindowUtils.dockedStackDividerInset)
+ dividerRegion.bounds.top + WindowUtils.dockedStackDividerInset)
} else {
- Region(0, 0, dividerRegion.bounds.left,
- dividerRegion.bounds.right - WindowUtils.dockedStackDividerInset)
+ Region(0, 0, dividerRegion.bounds.left + WindowUtils.dockedStackDividerInset,
+ displayBounds.bounds.bottom)
}
}
fun getSecondaryRegion(dividerRegion: Region, rotation: Int): Region {
val displayBounds = WindowUtils.getDisplayBounds(rotation)
return if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) {
- Region(0,
- dividerRegion.bounds.bottom - WindowUtils.dockedStackDividerInset,
- displayBounds.bounds.right,
- displayBounds.bounds.bottom - WindowUtils.dockedStackDividerInset)
+ Region(0, dividerRegion.bounds.bottom - WindowUtils.dockedStackDividerInset,
+ displayBounds.bounds.right, displayBounds.bounds.bottom)
} else {
- Region(dividerRegion.bounds.right, 0,
- displayBounds.bounds.right,
- displayBounds.bounds.bottom - WindowUtils.dockedStackDividerInset)
+ Region(dividerRegion.bounds.right - WindowUtils.dockedStackDividerInset, 0,
+ displayBounds.bounds.right, displayBounds.bounds.bottom)
}
}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenDockActivity.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenDockActivity.kt
index 91d51de..dbbbcd2 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenDockActivity.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenDockActivity.kt
@@ -18,7 +18,6 @@
import android.platform.test.annotations.Presubmit
import android.view.Surface
-import androidx.test.filters.FlakyTest
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
import com.android.server.wm.flicker.FlickerTestParameter
@@ -64,7 +63,7 @@
splitScreenApp.defaultWindowName, WindowManagerStateHelper.SPLASH_SCREEN_NAME,
WindowManagerStateHelper.SNAPSHOT_WINDOW_NAME, *HOME_WINDOW_TITLE)
- @FlakyTest(bugId = 169271943)
+ @Presubmit
@Test
fun dockedStackPrimaryBoundsIsVisible() =
testSpec.dockedStackPrimaryBoundsIsVisible(testSpec.config.startRotation,
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenFromDetachedRecentTask.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenFromDetachedRecentTask.kt
new file mode 100644
index 0000000..f91f634
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenFromDetachedRecentTask.kt
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.legacysplitscreen
+
+import android.platform.test.annotations.Presubmit
+import android.view.Surface
+import androidx.test.filters.RequiresDevice
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.FlickerTestParameterFactory
+import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.launchSplitScreen
+import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
+import com.android.wm.shell.flicker.dockedStackDividerIsVisible
+import com.android.wm.shell.flicker.helpers.SplitScreenHelper
+import org.junit.FixMethodOrder
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test enter split screen from a detached recent task
+ *
+ * To run this test: `atest WMShellFlickerTests:EnterSplitScreenFromDetachedRecentTask`
+ */
+@RequiresDevice
+@RunWith(Parameterized::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+class EnterSplitScreenFromDetachedRecentTask(
+ testSpec: FlickerTestParameter
+) : LegacySplitScreenTransition(testSpec) {
+
+ override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
+ get() = { configuration ->
+ cleanSetup(this, configuration)
+ setup {
+ eachRun {
+ splitScreenApp.launchViaIntent(wmHelper)
+ // Press back to remove the task, but it should still be shown in recent.
+ device.pressBack()
+ }
+ }
+ transitions {
+ device.launchSplitScreen(wmHelper)
+ }
+ }
+
+ override val ignoredWindows: List<String>
+ get() = listOf(LAUNCHER_PACKAGE_NAME,
+ WindowManagerStateHelper.SPLASH_SCREEN_NAME,
+ WindowManagerStateHelper.SNAPSHOT_WINDOW_NAME,
+ splitScreenApp.defaultWindowName)
+
+ @Presubmit
+ @Test
+ fun dockedStackDividerIsVisible() = testSpec.dockedStackDividerIsVisible()
+
+ @Presubmit
+ @Test
+ fun appWindowIsVisible() {
+ testSpec.assertWmEnd {
+ isVisible(splitScreenApp.defaultWindowName)
+ }
+ }
+
+ companion object {
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun getParams(): Collection<FlickerTestParameter> {
+ return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests(
+ repetitions = SplitScreenHelper.TEST_REPETITIONS,
+ supportedRotations = listOf(Surface.ROTATION_0) // bugId = 179116910
+ )
+ }
+ }
+}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenLaunchToSide.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenLaunchToSide.kt
index f975ed9..3ae6cfa 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenLaunchToSide.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenLaunchToSide.kt
@@ -18,7 +18,6 @@
import android.platform.test.annotations.Presubmit
import android.view.Surface
-import androidx.test.filters.FlakyTest
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
import com.android.server.wm.flicker.FlickerTestParameter
@@ -66,13 +65,13 @@
secondaryApp.defaultWindowName, WindowManagerStateHelper.SPLASH_SCREEN_NAME,
WindowManagerStateHelper.SNAPSHOT_WINDOW_NAME)
- @FlakyTest(bugId = 169271943)
+ @Presubmit
@Test
fun dockedStackPrimaryBoundsIsVisible() =
testSpec.dockedStackPrimaryBoundsIsVisible(testSpec.config.startRotation,
splitScreenApp.defaultWindowName)
- @FlakyTest(bugId = 169271943)
+ @Presubmit
@Test
fun dockedStackSecondaryBoundsIsVisible() =
testSpec.dockedStackSecondaryBoundsIsVisible(testSpec.config.startRotation,
@@ -80,7 +79,6 @@
@Presubmit
@Test
- // b/169271943
fun dockedStackDividerBecomesVisible() = testSpec.dockedStackDividerBecomesVisible()
@Presubmit
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppAndEnterSplitScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppAndEnterSplitScreen.kt
index 4a59c62..0b4cb0f 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppAndEnterSplitScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppAndEnterSplitScreen.kt
@@ -62,11 +62,11 @@
}
}
- @FlakyTest(bugId = 175687842)
+ @Presubmit
@Test
fun dockedStackDividerIsVisible() = testSpec.dockedStackDividerIsVisible()
- @FlakyTest(bugId = 175687842)
+ @Presubmit
@Test
fun dockedStackPrimaryBoundsIsVisible() =
testSpec.dockedStackPrimaryBoundsIsVisible(testSpec.config.startRotation,
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppInSplitScreenMode.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppInSplitScreenMode.kt
index 834821b..8909e97 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppInSplitScreenMode.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppInSplitScreenMode.kt
@@ -62,11 +62,11 @@
}
}
- @FlakyTest(bugId = 175687842)
+ @Presubmit
@Test
fun dockedStackDividerIsVisible() = testSpec.dockedStackDividerIsVisible()
- @FlakyTest(bugId = 175687842)
+ @Presubmit
@Test
fun dockedStackPrimaryBoundsIsVisible() = testSpec.dockedStackPrimaryBoundsIsVisible(
testSpec.config.startRotation, splitScreenApp.defaultWindowName)
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppAndEnterSplitScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppAndEnterSplitScreen.kt
index 8cf1990..e850b60 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppAndEnterSplitScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppAndEnterSplitScreen.kt
@@ -65,17 +65,17 @@
}
}
- @FlakyTest(bugId = 175687842)
+ @Presubmit
@Test
fun dockedStackDividerIsVisible() = testSpec.dockedStackDividerIsVisible()
- @FlakyTest(bugId = 175687842)
+ @Presubmit
@Test
fun dockedStackPrimaryBoundsIsVisible() =
testSpec.dockedStackPrimaryBoundsIsVisible(testSpec.config.startRotation,
splitScreenApp.defaultWindowName)
- @FlakyTest(bugId = 175687842)
+ @Presubmit
@Test
fun dockedStackSecondaryBoundsIsVisible() =
testSpec.dockedStackSecondaryBoundsIsVisible(testSpec.config.startRotation,
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppInSplitScreenMode.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppInSplitScreenMode.kt
index db709a0..cae2338 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppInSplitScreenMode.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppInSplitScreenMode.kt
@@ -70,17 +70,17 @@
}
}
- @FlakyTest(bugId = 175687842)
+ @Presubmit
@Test
fun dockedStackDividerIsVisible() = testSpec.dockedStackDividerIsVisible()
- @FlakyTest(bugId = 175687842)
+ @Presubmit
@Test
fun dockedStackPrimaryBoundsIsVisible() =
testSpec.dockedStackPrimaryBoundsIsVisible(testSpec.config.startRotation,
splitScreenApp.defaultWindowName)
- @FlakyTest(bugId = 175687842)
+ @Presubmit
@Test
fun dockedStackSecondaryBoundsIsVisible() =
testSpec.dockedStackSecondaryBoundsIsVisible(testSpec.config.startRotation,
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/apppairs/AppPairTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/apppairs/AppPairTests.java
index d21183e..e73d9aa 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/apppairs/AppPairTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/apppairs/AppPairTests.java
@@ -18,9 +18,12 @@
import static android.view.Display.DEFAULT_DISPLAY;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.ActivityManager;
@@ -43,7 +46,11 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-/** Tests for {@link AppPair} */
+/**
+ * Tests for {@link AppPair}
+ * Build/Install/Run:
+ * atest WMShellUnitTests:AppPairTests
+ */
@SmallTest
@RunWith(AndroidJUnit4.class)
public class AppPairTests extends ShellTestCase {
@@ -63,6 +70,7 @@
mTaskOrganizer,
mSyncQueue,
mDisplayController);
+ spyOn(mController);
}
@After
@@ -97,4 +105,19 @@
assertThat(pair.contains(task1.taskId)).isFalse();
assertThat(pair.contains(task2.taskId)).isFalse();
}
+
+ @Test
+ @UiThreadTest
+ public void testOnTaskInfoChanged_notSupportsMultiWindow() {
+ final ActivityManager.RunningTaskInfo task1 = new TestRunningTaskInfoBuilder().build();
+ final ActivityManager.RunningTaskInfo task2 = new TestRunningTaskInfoBuilder().build();
+
+ final AppPair pair = mController.pairInner(task1, task2);
+ assertThat(pair.contains(task1.taskId)).isTrue();
+ assertThat(pair.contains(task2.taskId)).isTrue();
+
+ task1.supportsMultiWindow = false;
+ pair.onTaskInfoChanged(task1);
+ verify(mController).unpair(pair.getRootTaskId());
+ }
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java
index 7b0e6b9..952dc31 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java
@@ -35,6 +35,7 @@
import androidx.test.filters.SmallTest;
import com.android.internal.policy.DividerSnapAlgorithm;
+import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.ShellTestCase;
import com.android.wm.shell.common.DisplayImeController;
@@ -48,9 +49,10 @@
@SmallTest
@RunWith(AndroidJUnit4.class)
public class SplitLayoutTests extends ShellTestCase {
- @Mock SplitLayout.LayoutChangeListener mLayoutChangeListener;
+ @Mock SplitLayout.SplitLayoutHandler mSplitLayoutHandler;
@Mock SurfaceControl mRootLeash;
@Mock DisplayImeController mDisplayImeController;
+ @Mock ShellTaskOrganizer mTaskOrganizer;
private SplitLayout mSplitLayout;
@Before
@@ -60,9 +62,10 @@
"TestSplitLayout",
mContext,
getConfiguration(false),
- mLayoutChangeListener,
+ mSplitLayoutHandler,
b -> b.setParent(mRootLeash),
- mDisplayImeController);
+ mDisplayImeController,
+ mTaskOrganizer);
}
@Test
@@ -76,19 +79,19 @@
@Test
public void testUpdateDivideBounds() {
mSplitLayout.updateDivideBounds(anyInt());
- verify(mLayoutChangeListener).onBoundsChanging(any(SplitLayout.class));
+ verify(mSplitLayoutHandler).onBoundsChanging(any(SplitLayout.class));
}
@Test
public void testSetDividePosition() {
mSplitLayout.setDividePosition(anyInt());
- verify(mLayoutChangeListener).onBoundsChanged(any(SplitLayout.class));
+ verify(mSplitLayoutHandler).onBoundsChanged(any(SplitLayout.class));
}
@Test
public void testOnDoubleTappedDivider() {
mSplitLayout.onDoubleTappedDivider();
- verify(mLayoutChangeListener).onDoubleTappedDivider();
+ verify(mSplitLayoutHandler).onDoubleTappedDivider();
}
@Test
@@ -98,11 +101,11 @@
DividerSnapAlgorithm.SnapTarget snapTarget = getSnapTarget(0 /* position */,
DividerSnapAlgorithm.SnapTarget.FLAG_DISMISS_START);
mSplitLayout.snapToTarget(0 /* currentPosition */, snapTarget);
- verify(mLayoutChangeListener).onSnappedToDismiss(eq(false));
+ verify(mSplitLayoutHandler).onSnappedToDismiss(eq(false));
snapTarget = getSnapTarget(0 /* position */,
DividerSnapAlgorithm.SnapTarget.FLAG_DISMISS_END);
mSplitLayout.snapToTarget(0 /* currentPosition */, snapTarget);
- verify(mLayoutChangeListener).onSnappedToDismiss(eq(true));
+ verify(mSplitLayoutHandler).onSnappedToDismiss(eq(true));
}
private static Configuration getConfiguration(boolean isLandscape) {
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitWindowManagerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitWindowManagerTests.java
index 86d0d82..698315a 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitWindowManagerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitWindowManagerTests.java
@@ -29,7 +29,6 @@
import androidx.test.filters.SmallTest;
import com.android.wm.shell.ShellTestCase;
-import com.android.wm.shell.common.DisplayImeController;
import org.junit.Before;
import org.junit.Test;
@@ -43,7 +42,6 @@
public class SplitWindowManagerTests extends ShellTestCase {
@Mock SurfaceControl mSurfaceControl;
@Mock SplitLayout mSplitLayout;
- @Mock DisplayImeController mDisplayImeController;
private SplitWindowManager mSplitWindowManager;
@Before
@@ -52,7 +50,7 @@
final Configuration configuration = new Configuration();
configuration.setToDefaults();
mSplitWindowManager = new SplitWindowManager("TestSplitDivider", mContext, configuration,
- b -> b.setParent(mSurfaceControl), mDisplayImeController);
+ b -> b.setParent(mSurfaceControl));
when(mSplitLayout.getDividerBounds()).thenReturn(
new Rect(0, 0, configuration.windowConfiguration.getBounds().width(),
configuration.windowConfiguration.getBounds().height()));
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropPolicyTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropPolicyTest.java
index 2f2bbba..ba73d55 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropPolicyTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropPolicyTest.java
@@ -24,13 +24,13 @@
import static android.content.ClipDescription.MIMETYPE_APPLICATION_SHORTCUT;
import static android.content.ClipDescription.MIMETYPE_APPLICATION_TASK;
+import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_BOTTOM_OR_RIGHT;
+import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_UNDEFINED;
import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_FULLSCREEN;
import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPLIT_BOTTOM;
import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPLIT_LEFT;
import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPLIT_RIGHT;
import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPLIT_TOP;
-import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_POSITION_BOTTOM_OR_RIGHT;
-import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_POSITION_UNDEFINED;
import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_SIDE;
import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_UNDEFINED;
@@ -206,7 +206,7 @@
mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData);
verify(mSplitScreenStarter).startIntent(any(), any(),
- eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED), any());
+ eq(STAGE_TYPE_UNDEFINED), eq(SPLIT_POSITION_UNDEFINED), any());
}
@Test
@@ -218,12 +218,12 @@
mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData);
verify(mSplitScreenStarter).startIntent(any(), any(),
- eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED), any());
+ eq(STAGE_TYPE_UNDEFINED), eq(SPLIT_POSITION_UNDEFINED), any());
reset(mSplitScreenStarter);
mPolicy.handleDrop(filterTargetByType(targets, TYPE_SPLIT_RIGHT), mActivityClipData);
verify(mSplitScreenStarter).startIntent(any(), any(),
- eq(STAGE_TYPE_SIDE), eq(STAGE_POSITION_BOTTOM_OR_RIGHT), any());
+ eq(STAGE_TYPE_SIDE), eq(SPLIT_POSITION_BOTTOM_OR_RIGHT), any());
}
@Test
@@ -235,12 +235,12 @@
mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData);
verify(mSplitScreenStarter).startIntent(any(), any(),
- eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED), any());
+ eq(STAGE_TYPE_UNDEFINED), eq(SPLIT_POSITION_UNDEFINED), any());
reset(mSplitScreenStarter);
mPolicy.handleDrop(filterTargetByType(targets, TYPE_SPLIT_BOTTOM), mActivityClipData);
verify(mSplitScreenStarter).startIntent(any(), any(),
- eq(STAGE_TYPE_SIDE), eq(STAGE_POSITION_BOTTOM_OR_RIGHT), any());
+ eq(STAGE_TYPE_SIDE), eq(SPLIT_POSITION_BOTTOM_OR_RIGHT), any());
}
@Test
@@ -252,7 +252,7 @@
mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData);
verify(mSplitScreenStarter).startIntent(any(), any(),
- eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED), any());
+ eq(STAGE_TYPE_UNDEFINED), eq(SPLIT_POSITION_UNDEFINED), any());
}
@Test
@@ -264,7 +264,7 @@
mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData);
verify(mSplitScreenStarter).startIntent(any(), any(),
- eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED), any());
+ eq(STAGE_TYPE_UNDEFINED), eq(SPLIT_POSITION_UNDEFINED), any());
}
@Test
@@ -277,13 +277,13 @@
mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData);
verify(mSplitScreenStarter).startIntent(any(), any(),
- eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED), any());
+ eq(STAGE_TYPE_UNDEFINED), eq(SPLIT_POSITION_UNDEFINED), any());
reset(mSplitScreenStarter);
// TODO(b/169894807): Just verify starting for the non-docked task until we have app pairs
mPolicy.handleDrop(filterTargetByType(targets, TYPE_SPLIT_RIGHT), mActivityClipData);
verify(mSplitScreenStarter).startIntent(any(), any(),
- eq(STAGE_TYPE_SIDE), eq(STAGE_POSITION_BOTTOM_OR_RIGHT), any());
+ eq(STAGE_TYPE_SIDE), eq(SPLIT_POSITION_BOTTOM_OR_RIGHT), any());
}
@Test
@@ -296,13 +296,13 @@
mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData);
verify(mSplitScreenStarter).startIntent(any(), any(),
- eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED), any());
+ eq(STAGE_TYPE_UNDEFINED), eq(SPLIT_POSITION_UNDEFINED), any());
reset(mSplitScreenStarter);
// TODO(b/169894807): Just verify starting for the non-docked task until we have app pairs
mPolicy.handleDrop(filterTargetByType(targets, TYPE_SPLIT_BOTTOM), mActivityClipData);
verify(mSplitScreenStarter).startIntent(any(), any(),
- eq(STAGE_TYPE_SIDE), eq(STAGE_POSITION_BOTTOM_OR_RIGHT), any());
+ eq(STAGE_TYPE_SIDE), eq(SPLIT_POSITION_BOTTOM_OR_RIGHT), any());
}
@Test
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java
index 99342f0..1852279 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java
@@ -28,7 +28,6 @@
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -79,8 +78,6 @@
@Mock
OneHandedTutorialHandler mMockTutorialHandler;
@Mock
- OneHandedGestureHandler mMockGestureHandler;
- @Mock
OneHandedSettingsUtil mMockSettingsUitl;
@Mock
OneHandedUiEventLogger mMockUiEventLogger;
@@ -131,7 +128,6 @@
mMockDisplayAreaOrganizer,
mMockTouchHandler,
mMockTutorialHandler,
- mMockGestureHandler,
mMockSettingsUitl,
mOneHandedAccessibilityUtil,
mSpiedTimeoutHandler,
@@ -179,7 +175,6 @@
@Test
public void testRegisterTransitionCallbackAfterInit() {
verify(mMockDisplayAreaOrganizer).registerTransitionCallback(mMockTouchHandler);
- verify(mMockDisplayAreaOrganizer).registerTransitionCallback(mMockGestureHandler);
verify(mMockDisplayAreaOrganizer).registerTransitionCallback(mMockTutorialHandler);
}
@@ -205,7 +200,6 @@
mSpiedOneHandedController.setOneHandedEnabled(true);
verify(mMockTouchHandler, atLeastOnce()).onOneHandedEnabled(anyBoolean());
- verify(mMockGestureHandler, atLeastOnce()).onGestureEnabled(anyBoolean());
}
@Test
@@ -213,7 +207,6 @@
mSpiedOneHandedController.setSwipeToNotificationEnabled(mDefaultSwipeToNotificationEnabled);
verify(mMockTouchHandler, atLeastOnce()).onOneHandedEnabled(anyBoolean());
- verify(mMockGestureHandler, atLeastOnce()).onGestureEnabled(anyBoolean());
}
@Test
@@ -340,30 +333,6 @@
}
@Test
- public void testDisabled3ButtonGestureWhenKeyguardOn() {
- final boolean isOneHandedEnabled = true;
- final boolean isLockWhenKeyguardOn = true;
- final boolean isEnabledWhenKeyguardOn = false;
- mSpiedOneHandedController.setOneHandedEnabled(isOneHandedEnabled);
- mSpiedOneHandedController.setLockedDisabled(isLockWhenKeyguardOn, isEnabledWhenKeyguardOn);
-
- verify(mMockGestureHandler).onGestureEnabled(isEnabledWhenKeyguardOn);
- }
-
- @Test
- public void testEnabled3ButtonGestureWhenKeyguardGoingAway() {
- final boolean isOneHandedEnabled = true;
- final boolean isLockWhenKeyguardOn = false;
- final boolean isEnabledWhenKeyguardOn = false;
- mSpiedOneHandedController.setOneHandedEnabled(isOneHandedEnabled);
- reset(mMockGestureHandler);
-
- mSpiedOneHandedController.setLockedDisabled(isLockWhenKeyguardOn, isEnabledWhenKeyguardOn);
-
- verify(mMockGestureHandler).onGestureEnabled(isOneHandedEnabled);
- }
-
- @Test
public void testStateActive_shortcutRequestActivate_skipActions() {
when(mSpiedTransitionState.getState()).thenReturn(STATE_ACTIVE);
when(mSpiedTransitionState.isTransitioning()).thenReturn(false);
@@ -429,4 +398,14 @@
verify(mSpiedOneHandedController, never()).startOneHanded();
verify(mSpiedOneHandedController, never()).stopOneHanded();
}
+
+ @Test
+ public void testControllerInit_tutorialAddStateChangeListener() {
+ when(mSpiedOneHandedController.isOneHandedEnabled()).thenReturn(true);
+ when(mSpiedTransitionState.getState()).thenReturn(STATE_NONE);
+ when(mSpiedTransitionState.isTransitioning()).thenReturn(false);
+ when(mMockSettingsUitl.getOneHandedModeActivated(any(), anyInt())).thenReturn(false);
+
+ verify(mSpiedTransitionState).addSListeners(mMockTutorialHandler);
+ }
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedGestureHandlerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedGestureHandlerTest.java
deleted file mode 100644
index 5d82a70..0000000
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedGestureHandlerTest.java
+++ /dev/null
@@ -1,129 +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.
- */
-
-package com.android.wm.shell.onehanded;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.testing.AndroidTestingRunner;
-import android.view.Surface;
-import android.view.ViewConfiguration;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.wm.shell.common.DisplayLayout;
-import com.android.wm.shell.common.ShellExecutor;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-public class OneHandedGestureHandlerTest extends OneHandedTestCase {
- OneHandedGestureHandler mGestureHandler;
- DisplayLayout mDisplayLayout;
- @Mock
- DisplayLayout mMockDisplayLayout;
- @Mock
- ShellExecutor mMockShellMainExecutor;
-
- @Before
- public void setUp() {
- final int mockNavBarHeight = 100;
- MockitoAnnotations.initMocks(this);
- mDisplayLayout = new DisplayLayout(mContext, mContext.getDisplay());
- mGestureHandler = new OneHandedGestureHandler(mContext, mDisplayLayout,
- ViewConfiguration.get(mTestContext), mMockShellMainExecutor);
- when(mMockDisplayLayout.navBarFrameHeight()).thenReturn(mockNavBarHeight);
- }
-
- @Test
- public void testSetGestureEventListener() {
- OneHandedGestureHandler.OneHandedGestureEventCallback callback =
- new OneHandedGestureHandler.OneHandedGestureEventCallback() {
- @Override
- public void onStart() {}
-
- @Override
- public void onStop() {}
- };
-
- mGestureHandler.setGestureEventListener(callback);
- assertThat(mGestureHandler.mGestureEventCallback).isEqualTo(callback);
- }
-
- @Test
- public void testOneHandedDisabled_shouldDisposeInputChannel() {
- mGestureHandler.onGestureEnabled(false);
-
- assertThat(mGestureHandler.mInputMonitor).isNull();
- assertThat(mGestureHandler.mInputEventReceiver).isNull();
- }
-
- @Test
- public void testChangeNavBarToNon3Button_shouldDisposeInputChannel() {
- mGestureHandler.onGestureEnabled(true);
- mGestureHandler.onThreeButtonModeEnabled(false);
-
- assertThat(mGestureHandler.mInputMonitor).isNull();
- assertThat(mGestureHandler.mInputEventReceiver).isNull();
- }
-
- @Test
- public void testOnlyHandleGestureInPortraitMode() {
- mDisplayLayout.rotateTo(mContext.getResources(), Surface.ROTATION_90);
- mGestureHandler.onGestureEnabled(true);
- mGestureHandler.onRotateDisplay(mDisplayLayout);
-
- assertThat(mGestureHandler.mInputMonitor).isNull();
- assertThat(mGestureHandler.mInputEventReceiver).isNull();
- }
-
- @Test
- public void testRotation90ShouldNotRegisterEventReceiver() throws InterruptedException {
- mDisplayLayout.rotateTo(mContext.getResources(), Surface.ROTATION_90);
- mGestureHandler.onGestureEnabled(true);
- mGestureHandler.onRotateDisplay(mDisplayLayout);
-
- verify(mMockShellMainExecutor, never()).executeBlocking(any());
- }
-
- @Test
- public void testRotation180ShouldNotRegisterEventReceiver() throws InterruptedException {
- mDisplayLayout.rotateTo(mContext.getResources(), Surface.ROTATION_180);
- mGestureHandler.onGestureEnabled(true);
- mGestureHandler.onRotateDisplay(mDisplayLayout);
-
- verify(mMockShellMainExecutor, never()).executeBlocking(any());
- }
-
- @Test
- public void testRotation270ShouldNotRegisterEventReceiver() throws InterruptedException {
- mDisplayLayout.rotateTo(mContext.getResources(), Surface.ROTATION_270);
- mGestureHandler.onGestureEnabled(true);
- mGestureHandler.onRotateDisplay(mDisplayLayout);
-
- verify(mMockShellMainExecutor, never()).executeBlocking(any());
- }
-}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedStateTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedStateTest.java
index 89aae65..e61f061 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedStateTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedStateTest.java
@@ -74,8 +74,6 @@
@Mock
OneHandedTutorialHandler mMockTutorialHandler;
@Mock
- OneHandedGestureHandler mMockGestureHandler;
- @Mock
OneHandedSettingsUtil mMockSettingsUitl;
@Mock
OneHandedUiEventLogger mMockUiEventLogger;
@@ -126,7 +124,6 @@
mMockDisplayAreaOrganizer,
mMockTouchHandler,
mMockTutorialHandler,
- mMockGestureHandler,
mMockSettingsUitl,
mOneHandedAccessibilityUtil,
mSpiedTimeoutHandler,
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTutorialHandlerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTutorialHandlerTest.java
index b82a8ca..1bc2a08 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTutorialHandlerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTutorialHandlerTest.java
@@ -16,19 +16,26 @@
package com.android.wm.shell.onehanded;
+import static com.android.wm.shell.onehanded.OneHandedState.STATE_ENTERING;
+import static com.android.wm.shell.onehanded.OneHandedState.STATE_NONE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import android.content.om.IOverlayManager;
-import android.os.Handler;
import android.testing.AndroidTestingRunner;
-import android.util.ArrayMap;
+import android.view.Display;
+import android.view.WindowManager;
import androidx.test.filters.SmallTest;
-import com.android.wm.shell.common.DisplayController;
+import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.common.ShellExecutor;
-import com.android.wm.shell.common.TaskStackListenerImpl;
import org.junit.Before;
import org.junit.Test;
@@ -39,65 +46,94 @@
@SmallTest
@RunWith(AndroidTestingRunner.class)
public class OneHandedTutorialHandlerTest extends OneHandedTestCase {
+ Display mDisplay;
+ DisplayLayout mDisplayLayout;
OneHandedTimeoutHandler mTimeoutHandler;
- OneHandedController mOneHandedController;
OneHandedState mSpiedTransitionState;
+ OneHandedTutorialHandler mSpiedTutorialHandler;
@Mock
- OneHandedGestureHandler mMockGestureHandler;
- @Mock
- OneHandedTouchHandler mMockTouchHandler;
- @Mock
- OneHandedTutorialHandler mMockTutorialHandler;
- @Mock
- DisplayController mMockDisplayController;
- @Mock
- OneHandedBackgroundPanelOrganizer mMockBackgroundOrganizer;
- @Mock
- OneHandedDisplayAreaOrganizer mMockDisplayAreaOrganizer;
- @Mock
- IOverlayManager mMockOverlayManager;
- @Mock
- TaskStackListenerImpl mMockTaskStackListener;
- @Mock
ShellExecutor mMockShellMainExecutor;
@Mock
- Handler mMockShellMainHandler;
- @Mock
- OneHandedUiEventLogger mMockUiEventLogger;
- @Mock
OneHandedSettingsUtil mMockSettingsUtil;
@Mock
- OneHandedAccessibilityUtil mMockAccessibilityUtil;
+ WindowManager mMockWindowManager;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- mTimeoutHandler = new OneHandedTimeoutHandler(mMockShellMainExecutor);
- mSpiedTransitionState = new OneHandedState();
+ when(mMockSettingsUtil.getTutorialShownCounts(any(), anyInt())).thenReturn(0);
- when(mMockDisplayAreaOrganizer.getDisplayAreaTokenMap()).thenReturn(new ArrayMap<>());
- mOneHandedController = new OneHandedController(
- mContext,
- mMockDisplayController,
- mMockBackgroundOrganizer,
- mMockDisplayAreaOrganizer,
- mMockTouchHandler,
- mMockTutorialHandler,
- mMockGestureHandler,
- mMockSettingsUtil,
- mMockAccessibilityUtil,
- mTimeoutHandler,
- mSpiedTransitionState,
- mMockUiEventLogger,
- mMockOverlayManager,
- mMockTaskStackListener,
- mMockShellMainExecutor,
- mMockShellMainHandler);
+ mDisplay = mContext.getDisplay();
+ mDisplayLayout = new DisplayLayout(mContext, mDisplay);
+ mSpiedTransitionState = spy(new OneHandedState());
+ mSpiedTutorialHandler = spy(
+ new OneHandedTutorialHandler(mContext, mDisplayLayout, mMockWindowManager,
+ mMockSettingsUtil, mMockShellMainExecutor));
+ mTimeoutHandler = new OneHandedTimeoutHandler(mMockShellMainExecutor);
}
@Test
- public void testRegisterForDisplayAreaOrganizer() {
- verify(mMockDisplayAreaOrganizer).registerTransitionCallback(mMockTutorialHandler);
+ public void testDefaultZeroShownCounts_canShowTutorial() {
+ assertThat(mSpiedTutorialHandler.canShowTutorial()).isTrue();
+ verify(mMockShellMainExecutor, never()).execute(any());
+ }
+
+ @Test
+ public void testDefaultZeroShownCounts_doNotAttachWindow() {
+ verify(mMockShellMainExecutor, never()).execute(any());
+ }
+
+ @Test
+ public void testOnStateChangedEntering_createViewAndAttachToWindow() {
+ when(mSpiedTutorialHandler.canShowTutorial()).thenReturn(true);
+ try {
+ mSpiedTutorialHandler.onStateChanged(STATE_ENTERING);
+ } catch (ClassCastException e) {
+ // no-op, just assert createViewAndAttachToWindow() to be called
+ }
+
+ verify(mSpiedTutorialHandler).createViewAndAttachToWindow(any());
+ }
+
+ @Test
+ public void testOnStateChangedNone_removeViewAndAttachToWindow() {
+ when(mSpiedTutorialHandler.canShowTutorial()).thenReturn(true);
+ try {
+ mSpiedTutorialHandler.onStateChanged(STATE_NONE);
+ } catch (ClassCastException e) {
+ // no-op, just assert removeTutorialFromWindowManager() to be called
+ }
+
+ verify(mSpiedTutorialHandler).removeTutorialFromWindowManager(true);
+ }
+
+ @Test
+ public void testOnStateChangedNone_shouldNotAttachWindow() {
+ when(mSpiedTutorialHandler.canShowTutorial()).thenReturn(true);
+ try {
+ mSpiedTutorialHandler.onStateChanged(STATE_NONE);
+ } catch (ClassCastException e) {
+ // no-op, just assert setTutorialShownCountIncrement() never be called
+ }
+
+ verify(mSpiedTutorialHandler, never()).setTutorialShownCountIncrement();
+ }
+
+ @Test
+ public void testOnConfigurationChanged_shouldUpdateViewContent() {
+ when(mSpiedTutorialHandler.canShowTutorial()).thenReturn(true);
+ try {
+ mSpiedTutorialHandler.onStateChanged(STATE_ENTERING);
+ } catch (ClassCastException e) {
+ // no-op, set current state for test onConfigurationChanged()
+ }
+ try {
+ mSpiedTutorialHandler.onConfigurationChanged();
+ } catch (ClassCastException e) {
+ // no-op, just assert removeTutorialFromWindowManager() be called
+ }
+
+ verify(mSpiedTutorialHandler).removeTutorialFromWindowManager(false);
}
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java
index c61302b..935f669 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java
@@ -30,6 +30,7 @@
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
+import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.RemoteException;
import android.test.suitebuilder.annotation.SmallTest;
@@ -40,12 +41,14 @@
import com.android.wm.shell.ShellTestCase;
import com.android.wm.shell.WindowManagerShellWrapper;
import com.android.wm.shell.common.DisplayController;
+import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.TaskStackListenerImpl;
import com.android.wm.shell.onehanded.OneHandedController;
import com.android.wm.shell.pip.PipBoundsAlgorithm;
import com.android.wm.shell.pip.PipBoundsState;
import com.android.wm.shell.pip.PipMediaController;
+import com.android.wm.shell.pip.PipSnapAlgorithm;
import com.android.wm.shell.pip.PipTaskOrganizer;
import com.android.wm.shell.pip.PipTransitionController;
@@ -70,16 +73,21 @@
@Mock private PhonePipMenuController mMockPhonePipMenuController;
@Mock private PipAppOpsListener mMockPipAppOpsListener;
@Mock private PipBoundsAlgorithm mMockPipBoundsAlgorithm;
+ @Mock private PipSnapAlgorithm mMockPipSnapAlgorithm;
@Mock private PipMediaController mMockPipMediaController;
@Mock private PipTaskOrganizer mMockPipTaskOrganizer;
@Mock private PipTransitionController mMockPipTransitionController;
@Mock private PipTouchHandler mMockPipTouchHandler;
+ @Mock private PipMotionHelper mMockPipMotionHelper;
@Mock private WindowManagerShellWrapper mMockWindowManagerShellWrapper;
@Mock private PipBoundsState mMockPipBoundsState;
@Mock private TaskStackListenerImpl mMockTaskStackListener;
@Mock private ShellExecutor mMockExecutor;
@Mock private Optional<OneHandedController> mMockOneHandedController;
+ @Mock private DisplayLayout mMockDisplayLayout1;
+ @Mock private DisplayLayout mMockDisplayLayout2;
+
@Before
public void setUp() throws RemoteException {
MockitoAnnotations.initMocks(this);
@@ -92,6 +100,8 @@
mMockPipMediaController, mMockPhonePipMenuController, mMockPipTaskOrganizer,
mMockPipTouchHandler, mMockPipTransitionController, mMockWindowManagerShellWrapper,
mMockTaskStackListener, mMockOneHandedController, mMockExecutor);
+ when(mMockPipBoundsAlgorithm.getSnapAlgorithm()).thenReturn(mMockPipSnapAlgorithm);
+ when(mMockPipTouchHandler.getMotionHelper()).thenReturn(mMockPipMotionHelper);
}
@Test
@@ -167,4 +177,36 @@
verify(mMockPipBoundsState).saveReentryState(new Size(30, 30), 1.0f);
}
+
+ @Test
+ public void onDisplayConfigurationChanged_inPip_movePip() {
+ final int displayId = 1;
+ final Rect bounds = new Rect(0, 0, 10, 10);
+ when(mMockPipBoundsAlgorithm.getDefaultBounds()).thenReturn(bounds);
+ when(mMockPipBoundsState.getDisplayId()).thenReturn(displayId);
+ when(mMockPipBoundsState.getDisplayLayout()).thenReturn(mMockDisplayLayout1);
+ when(mMockDisplayController.getDisplayLayout(displayId)).thenReturn(mMockDisplayLayout2);
+
+ when(mMockPipTaskOrganizer.isInPip()).thenReturn(true);
+ mPipController.mDisplaysChangedListener.onDisplayConfigurationChanged(
+ displayId, new Configuration());
+
+ verify(mMockPipMotionHelper).movePip(any(Rect.class));
+ }
+
+ @Test
+ public void onDisplayConfigurationChanged_notInPip_doesNotMovePip() {
+ final int displayId = 1;
+ final Rect bounds = new Rect(0, 0, 10, 10);
+ when(mMockPipBoundsAlgorithm.getDefaultBounds()).thenReturn(bounds);
+ when(mMockPipBoundsState.getDisplayId()).thenReturn(displayId);
+ when(mMockPipBoundsState.getDisplayLayout()).thenReturn(mMockDisplayLayout1);
+ when(mMockDisplayController.getDisplayLayout(displayId)).thenReturn(mMockDisplayLayout2);
+
+ when(mMockPipTaskOrganizer.isInPip()).thenReturn(false);
+ mPipController.mDisplaysChangedListener.onDisplayConfigurationChanged(
+ displayId, new Configuration());
+
+ verify(mMockPipMotionHelper, never()).movePip(any(Rect.class));
+ }
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/MainStageTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/MainStageTests.java
index 702e894..1bb5fd1 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/MainStageTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/MainStageTests.java
@@ -22,6 +22,7 @@
import android.app.ActivityManager;
import android.view.SurfaceControl;
+import android.view.SurfaceSession;
import android.window.WindowContainerTransaction;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -36,7 +37,6 @@
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import org.mockito.Spy;
/** Tests for {@link MainStage} */
@SmallTest
@@ -47,14 +47,16 @@
@Mock private SyncTransactionQueue mSyncQueue;
@Mock private ActivityManager.RunningTaskInfo mRootTaskInfo;
@Mock private SurfaceControl mRootLeash;
- @Spy private WindowContainerTransaction mWct;
+ private WindowContainerTransaction mWct = new WindowContainerTransaction();
+ private SurfaceSession mSurfaceSession = new SurfaceSession();
private MainStage mMainStage;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
mRootTaskInfo = new TestRunningTaskInfoBuilder().build();
- mMainStage = new MainStage(mTaskOrganizer, DEFAULT_DISPLAY, mCallbacks, mSyncQueue);
+ mMainStage = new MainStage(mTaskOrganizer, DEFAULT_DISPLAY, mCallbacks, mSyncQueue,
+ mSurfaceSession);
mMainStage.onTaskAppeared(mRootTaskInfo, mRootLeash);
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SideStageTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SideStageTests.java
index 01888b7..56a0056 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SideStageTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SideStageTests.java
@@ -26,6 +26,7 @@
import android.app.ActivityManager;
import android.view.SurfaceControl;
+import android.view.SurfaceSession;
import android.window.WindowContainerTransaction;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -52,13 +53,15 @@
@Mock private ActivityManager.RunningTaskInfo mRootTask;
@Mock private SurfaceControl mRootLeash;
@Spy private WindowContainerTransaction mWct;
+ private SurfaceSession mSurfaceSession = new SurfaceSession();
private SideStage mSideStage;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
mRootTask = new TestRunningTaskInfoBuilder().build();
- mSideStage = new SideStage(mTaskOrganizer, DEFAULT_DISPLAY, mCallbacks, mSyncQueue);
+ mSideStage = new SideStage(mTaskOrganizer, DEFAULT_DISPLAY, mCallbacks, mSyncQueue,
+ mSurfaceSession);
mSideStage.onTaskAppeared(mRootTask, mRootLeash);
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java
index 08ac2a6..aca80f3 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java
@@ -43,6 +43,7 @@
import android.os.IBinder;
import android.os.RemoteException;
import android.view.SurfaceControl;
+import android.view.SurfaceSession;
import android.window.IRemoteTransition;
import android.window.IRemoteTransitionFinishedCallback;
import android.window.TransitionInfo;
@@ -80,6 +81,7 @@
@Mock private DisplayImeController mDisplayImeController;
@Mock private TransactionPool mTransactionPool;
@Mock private Transitions mTransitions;
+ @Mock private SurfaceSession mSurfaceSession;
private SplitLayout mSplitLayout;
private MainStage mMainStage;
private SideStage mSideStage;
@@ -98,10 +100,10 @@
doReturn(mock(SurfaceControl.Transaction.class)).when(mTransactionPool).acquire();
mSplitLayout = SplitTestUtils.createMockSplitLayout();
mMainStage = new MainStage(mTaskOrganizer, DEFAULT_DISPLAY, mock(
- StageTaskListener.StageListenerCallbacks.class), mSyncQueue);
+ StageTaskListener.StageListenerCallbacks.class), mSyncQueue, mSurfaceSession);
mMainStage.onTaskAppeared(new TestRunningTaskInfoBuilder().build(), createMockSurface());
mSideStage = new SideStage(mTaskOrganizer, DEFAULT_DISPLAY, mock(
- StageTaskListener.StageListenerCallbacks.class), mSyncQueue);
+ StageTaskListener.StageListenerCallbacks.class), mSyncQueue, mSurfaceSession);
mSideStage.onTaskAppeared(new TestRunningTaskInfoBuilder().build(), createMockSurface());
mStageCoordinator = new SplitTestUtils.TestStageCoordinator(mContext, DEFAULT_DISPLAY,
mSyncQueue, mRootTDAOrganizer, mTaskOrganizer, mMainStage, mSideStage,
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
index 924e946..06b0868 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
@@ -18,7 +18,7 @@
import static android.view.Display.DEFAULT_DISPLAY;
-import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_POSITION_BOTTOM_OR_RIGHT;
+import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_BOTTOM_OR_RIGHT;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
@@ -73,7 +73,7 @@
public void testMoveToSideStage() {
final ActivityManager.RunningTaskInfo task = new TestRunningTaskInfoBuilder().build();
- mStageCoordinator.moveToSideStage(task, STAGE_POSITION_BOTTOM_OR_RIGHT);
+ mStageCoordinator.moveToSideStage(task, SPLIT_POSITION_BOTTOM_OR_RIGHT);
verify(mMainStage).activate(any(Rect.class), any(WindowContainerTransaction.class));
verify(mSideStage).addTask(eq(task), any(Rect.class),
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java
index c66e073..90b5b37 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java
@@ -27,6 +27,7 @@
import android.app.ActivityManager;
import android.view.SurfaceControl;
+import android.view.SurfaceSession;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
@@ -38,16 +39,24 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-/** Tests for {@link StageTaskListener} */
+/**
+ * Tests for {@link StageTaskListener}
+ * Build/Install/Run:
+ * atest WMShellUnitTests:StageTaskListenerTests
+ */
@SmallTest
@RunWith(AndroidJUnit4.class)
public final class StageTaskListenerTests {
@Mock private ShellTaskOrganizer mTaskOrganizer;
@Mock private StageTaskListener.StageListenerCallbacks mCallbacks;
@Mock private SyncTransactionQueue mSyncQueue;
+ @Captor private ArgumentCaptor<SyncTransactionQueue.TransactionRunnable> mRunnableCaptor;
+ private SurfaceSession mSurfaceSession = new SurfaceSession();
private ActivityManager.RunningTaskInfo mRootTask;
private StageTaskListener mStageTaskListener;
@@ -58,13 +67,24 @@
mTaskOrganizer,
DEFAULT_DISPLAY,
mCallbacks,
- mSyncQueue);
+ mSyncQueue,
+ mSurfaceSession);
mRootTask = new TestRunningTaskInfoBuilder().build();
mRootTask.parentTaskId = INVALID_TASK_ID;
mStageTaskListener.onTaskAppeared(mRootTask, new SurfaceControl());
}
@Test
+ public void testInitsDimLayer() {
+ verify(mSyncQueue).runInSync(mRunnableCaptor.capture());
+ final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+ mRunnableCaptor.getValue().runWithTransaction(t);
+ t.apply();
+
+ assertThat(mStageTaskListener.mDimLayer).isNotNull();
+ }
+
+ @Test
public void testRootTaskAppeared() {
assertThat(mStageTaskListener.mRootTaskInfo.taskId).isEqualTo(mRootTask.taskId);
verify(mCallbacks).onRootTaskAppeared();
@@ -101,4 +121,14 @@
mStageTaskListener.onTaskVanished(mRootTask);
verify(mCallbacks).onRootTaskVanished();
}
+
+ @Test
+ public void testTaskInfoChanged_notSupportsMultiWindow() {
+ final ActivityManager.RunningTaskInfo childTask =
+ new TestRunningTaskInfoBuilder().setParentTaskId(mRootTask.taskId).build();
+ childTask.supportsMultiWindow = false;
+
+ mStageTaskListener.onTaskInfoChanged(childTask);
+ verify(mCallbacks).onNoLongerSupportMultiWindow();
+ }
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/TaskSnapshotWindowTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/TaskSnapshotWindowTest.java
index b908df2..5945840 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/TaskSnapshotWindowTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/TaskSnapshotWindowTest.java
@@ -16,7 +16,6 @@
package com.android.wm.shell.startingsurface;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
@@ -82,7 +81,7 @@
mWindow = new TaskSnapshotWindow(new SurfaceControl(), snapshot, "Test",
createTaskDescription(Color.WHITE, Color.RED, Color.BLUE),
0 /* appearance */, windowFlags /* windowFlags */, 0 /* privateWindowFlags */,
- taskBounds, ORIENTATION_PORTRAIT, ACTIVITY_TYPE_STANDARD, new InsetsState(),
+ taskBounds, ORIENTATION_PORTRAIT, new InsetsState(),
null /* clearWindow */, new TestShellExecutor());
}
diff --git a/libs/androidfw/ApkAssets.cpp b/libs/androidfw/ApkAssets.cpp
index 76366fc..26d8363 100755
--- a/libs/androidfw/ApkAssets.cpp
+++ b/libs/androidfw/ApkAssets.cpp
@@ -88,7 +88,7 @@
if (IsFabricatedOverlay(overlay_path)) {
// Fabricated overlays do not contain resource definitions. All of the overlay resource values
// are defined inline in the idmap.
- overlay_assets = EmptyAssetsProvider::Create();
+ overlay_assets = EmptyAssetsProvider::Create(overlay_path);
} else {
// The overlay should be an APK.
overlay_assets = ZipAssetsProvider::Create(overlay_path);
diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp
index 320106a..3a0153f 100644
--- a/libs/androidfw/AssetManager2.cpp
+++ b/libs/androidfw/AssetManager2.cpp
@@ -612,6 +612,11 @@
result->entry = overlay_entry.GetInlineValue();
result->dynamic_ref_table = id_map.overlay_res_maps_.GetOverlayDynamicRefTable();
result->cookie = id_map.cookie;
+
+ if (UNLIKELY(logging_enabled)) {
+ last_resolution_.steps.push_back(
+ Resolution::Step{Resolution::Step::Type::OVERLAID_INLINE, String8(), result->cookie});
+ }
continue;
}
@@ -640,7 +645,6 @@
if (UNLIKELY(logging_enabled)) {
last_resolution_.steps.push_back(
Resolution::Step{Resolution::Step::Type::OVERLAID, overlay_result->config.toString(),
- overlay_result->package_name,
overlay_result->cookie});
}
}
@@ -723,7 +727,6 @@
if (UNLIKELY(logging_enabled)) {
resolution_steps.push_back(Resolution::Step{Resolution::Step::Type::SKIPPED,
this_config.toString(),
- &loaded_package->GetPackageName(),
cookie});
}
continue;
@@ -741,7 +744,6 @@
if (UNLIKELY(logging_enabled)) {
resolution_steps.push_back(Resolution::Step{Resolution::Step::Type::NO_ENTRY,
this_config.toString(),
- &loaded_package->GetPackageName(),
cookie});
}
continue;
@@ -756,7 +758,6 @@
if (UNLIKELY(logging_enabled)) {
last_resolution_.steps.push_back(Resolution::Step{resolution_type,
this_config.toString(),
- &loaded_package->GetPackageName(),
cookie});
}
@@ -839,18 +840,18 @@
}
std::stringstream log_stream;
- log_stream << base::StringPrintf("Resolution for 0x%08x ", resid)
- << resource_name_string
- << "\n\tFor config -"
- << configuration_.toString();
+ log_stream << base::StringPrintf("Resolution for 0x%08x %s\n"
+ "\tFor config - %s", resid, resource_name_string.c_str(),
+ configuration_.toString().c_str());
for (const Resolution::Step& step : last_resolution_.steps) {
const static std::unordered_map<Resolution::Step::Type, const char*> kStepStrings = {
- {Resolution::Step::Type::INITIAL, "Found initial"},
- {Resolution::Step::Type::BETTER_MATCH, "Found better"},
- {Resolution::Step::Type::OVERLAID, "Overlaid"},
- {Resolution::Step::Type::SKIPPED, "Skipped"},
- {Resolution::Step::Type::NO_ENTRY, "No entry"}
+ {Resolution::Step::Type::INITIAL, "Found initial"},
+ {Resolution::Step::Type::BETTER_MATCH, "Found better"},
+ {Resolution::Step::Type::OVERLAID, "Overlaid"},
+ {Resolution::Step::Type::OVERLAID_INLINE, "Overlaid inline"},
+ {Resolution::Step::Type::SKIPPED, "Skipped"},
+ {Resolution::Step::Type::NO_ENTRY, "No entry"}
};
const auto prefix = kStepStrings.find(step.type);
@@ -858,10 +859,9 @@
continue;
}
- log_stream << "\n\t" << prefix->second << ": " << *step.package_name << " ("
- << apk_assets_[step.cookie]->GetDebugName() << ")";
+ log_stream << "\n\t" << prefix->second << ": " << apk_assets_[step.cookie]->GetDebugName();
if (!step.config_name.isEmpty()) {
- log_stream << " -" << step.config_name;
+ log_stream << " - " << step.config_name;
}
}
diff --git a/libs/androidfw/AssetsProvider.cpp b/libs/androidfw/AssetsProvider.cpp
index 0aaf0b3..6c7a253 100644
--- a/libs/androidfw/AssetsProvider.cpp
+++ b/libs/androidfw/AssetsProvider.cpp
@@ -386,8 +386,15 @@
return primary_->IsUpToDate() && secondary_->IsUpToDate();
}
+EmptyAssetsProvider::EmptyAssetsProvider(std::optional<std::string>&& path) :
+ path_(std::move(path)) {}
+
std::unique_ptr<AssetsProvider> EmptyAssetsProvider::Create() {
- return std::make_unique<EmptyAssetsProvider>();
+ return std::unique_ptr<EmptyAssetsProvider>(new EmptyAssetsProvider({}));
+}
+
+std::unique_ptr<AssetsProvider> EmptyAssetsProvider::Create(const std::string& path) {
+ return std::unique_ptr<EmptyAssetsProvider>(new EmptyAssetsProvider(path));
}
std::unique_ptr<Asset> EmptyAssetsProvider::OpenInternal(const std::string& /* path */,
@@ -406,10 +413,16 @@
}
std::optional<std::string_view> EmptyAssetsProvider::GetPath() const {
+ if (path_.has_value()) {
+ return *path_;
+ }
return {};
}
const std::string& EmptyAssetsProvider::GetDebugName() const {
+ if (path_.has_value()) {
+ return *path_;
+ }
const static std::string kEmpty = kEmptyDebugString;
return kEmpty;
}
diff --git a/libs/androidfw/include/androidfw/AssetManager2.h b/libs/androidfw/include/androidfw/AssetManager2.h
index 10666ad..df3abf6 100644
--- a/libs/androidfw/include/androidfw/AssetManager2.h
+++ b/libs/androidfw/include/androidfw/AssetManager2.h
@@ -458,6 +458,7 @@
INITIAL,
BETTER_MATCH,
OVERLAID,
+ OVERLAID_INLINE,
SKIPPED,
NO_ENTRY,
};
@@ -468,10 +469,6 @@
// Built name of configuration for this step.
String8 config_name;
- // Marks the package name of the better resource found in this step.
- const std::string* package_name;
-
- //
ApkAssetsCookie cookie = kInvalidCookie;
};
diff --git a/libs/androidfw/include/androidfw/AssetsProvider.h b/libs/androidfw/include/androidfw/AssetsProvider.h
index 63bbdcc..ec51c65 100644
--- a/libs/androidfw/include/androidfw/AssetsProvider.h
+++ b/libs/androidfw/include/androidfw/AssetsProvider.h
@@ -176,6 +176,7 @@
// Does not provide any assets.
struct EmptyAssetsProvider : public AssetsProvider {
static std::unique_ptr<AssetsProvider> Create();
+ static std::unique_ptr<AssetsProvider> Create(const std::string& path);
bool ForEachFile(const std::string& path,
const std::function<void(const StringPiece&, FileType)>& f) const override;
@@ -188,6 +189,10 @@
protected:
std::unique_ptr<Asset> OpenInternal(const std::string& path, Asset::AccessMode mode,
bool* file_exists) const override;
+
+ private:
+ explicit EmptyAssetsProvider(std::optional<std::string>&& path);
+ std::optional<std::string> path_;
};
} // namespace android
diff --git a/libs/androidfw/tests/AssetManager2_test.cpp b/libs/androidfw/tests/AssetManager2_test.cpp
index e1c0fab7..3c4ee4e 100644
--- a/libs/androidfw/tests/AssetManager2_test.cpp
+++ b/libs/androidfw/tests/AssetManager2_test.cpp
@@ -765,7 +765,8 @@
auto result = assetmanager.GetLastResourceResolution();
EXPECT_EQ("Resolution for 0x7f030000 com.android.basic:string/test1\n"
- "\tFor config -de\n\tFound initial: com.android.basic (basic/basic.apk)", result);
+ "\tFor config - de\n"
+ "\tFound initial: basic/basic.apk", result);
}
TEST_F(AssetManager2Test, GetLastPathWithMultipleApkAssets) {
@@ -784,9 +785,9 @@
auto result = assetmanager.GetLastResourceResolution();
EXPECT_EQ("Resolution for 0x7f030000 com.android.basic:string/test1\n"
- "\tFor config -de\n"
- "\tFound initial: com.android.basic (basic/basic.apk)\n"
- "\tFound better: com.android.basic (basic/basic_de_fr.apk) -de", result);
+ "\tFor config - de\n"
+ "\tFound initial: basic/basic.apk\n"
+ "\tFound better: basic/basic_de_fr.apk - de", result);
}
TEST_F(AssetManager2Test, GetLastPathAfterDisablingReturnsEmpty) {
diff --git a/libs/hwui/DamageAccumulator.cpp b/libs/hwui/DamageAccumulator.cpp
index 0adc0f6..9db47c3 100644
--- a/libs/hwui/DamageAccumulator.cpp
+++ b/libs/hwui/DamageAccumulator.cpp
@@ -157,7 +157,7 @@
static inline void mapRect(const RenderProperties& props, const SkRect& in, SkRect* out) {
if (in.isEmpty()) return;
SkRect temp(in);
- if (Properties::stretchEffectBehavior == StretchEffectBehavior::UniformScale) {
+ if (Properties::getStretchEffectBehavior() == StretchEffectBehavior::UniformScale) {
const StretchEffect& stretch = props.layerProperties().getStretchEffect();
if (!stretch.isEmpty()) {
applyMatrix(stretch.makeLinearStretch(props.getWidth(), props.getHeight()), &temp);
diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp
index a4614a9..f0995c4 100644
--- a/libs/hwui/Properties.cpp
+++ b/libs/hwui/Properties.cpp
@@ -137,10 +137,6 @@
targetCpuTimePercentage = base::GetIntProperty(PROPERTY_TARGET_CPU_TIME_PERCENTAGE, 70);
if (targetCpuTimePercentage <= 0 || targetCpuTimePercentage > 100) targetCpuTimePercentage = 70;
- int stretchType = base::GetIntProperty(PROPERTY_STRETCH_EFFECT_TYPE, 0);
- stretchType = std::clamp(stretchType, 0, static_cast<int>(StretchEffectBehavior::UniformScale));
- stretchEffectBehavior = static_cast<StretchEffectBehavior>(stretchType);
-
return (prevDebugLayersUpdates != debugLayersUpdates) || (prevDebugOverdraw != debugOverdraw);
}
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index 9964254..f5fd003 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -171,8 +171,6 @@
*/
#define PROPERTY_TARGET_CPU_TIME_PERCENTAGE "debug.hwui.target_cpu_time_percent"
-#define PROPERTY_STRETCH_EFFECT_TYPE "debug.hwui.stretch_mode"
-
/**
* Property for whether this is running in the emulator.
*/
@@ -278,9 +276,26 @@
static bool useHintManager;
static int targetCpuTimePercentage;
- static StretchEffectBehavior stretchEffectBehavior;
+ static StretchEffectBehavior getStretchEffectBehavior() {
+ return stretchEffectBehavior;
+ }
+
+ static void setIsHighEndGfx(bool isHighEndGfx) {
+ stretchEffectBehavior = isHighEndGfx ?
+ StretchEffectBehavior::ShaderHWUI :
+ StretchEffectBehavior::UniformScale;
+ }
+
+ /**
+ * Used for testing. Typical configuration of stretch behavior is done
+ * through setIsHighEndGfx
+ */
+ static void setStretchEffectBehavior(StretchEffectBehavior behavior) {
+ stretchEffectBehavior = behavior;
+ }
private:
+ static StretchEffectBehavior stretchEffectBehavior;
static ProfileType sProfileType;
static bool sDisableProfileBars;
static RenderPipelineType sRenderPipelineType;
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index ad2cd8c..ded7994 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -478,7 +478,7 @@
}
}
- if (Properties::stretchEffectBehavior == StretchEffectBehavior::UniformScale) {
+ if (Properties::getStretchEffectBehavior() == StretchEffectBehavior::UniformScale) {
const StretchEffect& stretch = properties().layerProperties().getStretchEffect();
if (!stretch.isEmpty()) {
matrix.multiply(
diff --git a/libs/hwui/WebViewFunctorManager.cpp b/libs/hwui/WebViewFunctorManager.cpp
index 979678d..d9b9e24 100644
--- a/libs/hwui/WebViewFunctorManager.cpp
+++ b/libs/hwui/WebViewFunctorManager.cpp
@@ -221,8 +221,30 @@
return sInstance;
}
+static void validateCallbacks(const WebViewFunctorCallbacks& callbacks) {
+ // TODO: Should we do a stack peek to see if this is really webview?
+ LOG_ALWAYS_FATAL_IF(callbacks.onSync == nullptr, "onSync is null");
+ LOG_ALWAYS_FATAL_IF(callbacks.onContextDestroyed == nullptr, "onContextDestroyed is null");
+ LOG_ALWAYS_FATAL_IF(callbacks.onDestroyed == nullptr, "onDestroyed is null");
+ LOG_ALWAYS_FATAL_IF(callbacks.removeOverlays == nullptr, "removeOverlays is null");
+ switch (auto mode = WebViewFunctor_queryPlatformRenderMode()) {
+ case RenderMode::OpenGL_ES:
+ LOG_ALWAYS_FATAL_IF(callbacks.gles.draw == nullptr, "gles.draw is null");
+ break;
+ case RenderMode::Vulkan:
+ LOG_ALWAYS_FATAL_IF(callbacks.vk.initialize == nullptr, "vk.initialize is null");
+ LOG_ALWAYS_FATAL_IF(callbacks.vk.draw == nullptr, "vk.draw is null");
+ LOG_ALWAYS_FATAL_IF(callbacks.vk.postDraw == nullptr, "vk.postDraw is null");
+ break;
+ default:
+ LOG_ALWAYS_FATAL("unknown platform mode? %d", (int)mode);
+ break;
+ }
+}
+
int WebViewFunctorManager::createFunctor(void* data, const WebViewFunctorCallbacks& callbacks,
RenderMode functorMode) {
+ validateCallbacks(callbacks);
auto object = std::make_unique<WebViewFunctor>(data, callbacks, functorMode);
int id = object->id();
auto handle = object->createHandle();
diff --git a/libs/hwui/effects/StretchEffect.cpp b/libs/hwui/effects/StretchEffect.cpp
index 0599bfa..807fb75 100644
--- a/libs/hwui/effects/StretchEffect.cpp
+++ b/libs/hwui/effects/StretchEffect.cpp
@@ -94,13 +94,14 @@
float uStretchAffectedDist,
float uInverseStretchAffectedDist,
float distanceStretched,
- float interpolationStrength
+ float interpolationStrength,
+ float viewportDimension
) {
float offsetPos = inPos - reverseStretchDist;
float posBasedVariation = mix(
1. ,easeIn(offsetPos, uInverseStretchAffectedDist), interpolationStrength);
float stretchIntensity = (-overscroll) * posBasedVariation;
- return 1 - (distanceStretched - (offsetPos / (1. + stretchIntensity)));
+ return viewportDimension - (distanceStretched - (offsetPos / (1. + stretchIntensity)));
}
// Prefer usage of return values over out parameters as it enables
@@ -113,54 +114,51 @@
float uInverseStretchAffectedDist,
float distanceStretched,
float distanceDiff,
- float interpolationStrength
+ float interpolationStrength,
+ float viewportDimension
) {
- float outPos = inPos;
if (overscroll > 0) {
- if (inPos <= uStretchAffectedDist) {
- outPos = computeOverscrollStart(
- inPos,
- overscroll,
- uStretchAffectedDist,
- uInverseStretchAffectedDist,
- distanceStretched,
- interpolationStrength
- );
- } else if (inPos >= distanceStretched) {
- outPos = distanceDiff + inPos;
- }
+ if (inPos <= uStretchAffectedDist) {
+ return computeOverscrollStart(
+ inPos,
+ overscroll,
+ uStretchAffectedDist,
+ uInverseStretchAffectedDist,
+ distanceStretched,
+ interpolationStrength
+ );
+ } else {
+ return distanceDiff + inPos;
}
- if (overscroll < 0) {
- float stretchAffectedDist = 1. - uStretchAffectedDist;
- if (inPos >= stretchAffectedDist) {
- outPos = computeOverscrollEnd(
- inPos,
- overscroll,
- stretchAffectedDist,
- uStretchAffectedDist,
- uInverseStretchAffectedDist,
- distanceStretched,
- interpolationStrength
- );
- } else if (inPos < stretchAffectedDist) {
- outPos = -distanceDiff + inPos;
- }
+ } else if (overscroll < 0) {
+ float stretchAffectedDist = viewportDimension - uStretchAffectedDist;
+ if (inPos >= stretchAffectedDist) {
+ return computeOverscrollEnd(
+ inPos,
+ overscroll,
+ stretchAffectedDist,
+ uStretchAffectedDist,
+ uInverseStretchAffectedDist,
+ distanceStretched,
+ interpolationStrength,
+ viewportDimension
+ );
+ } else {
+ return -distanceDiff + inPos;
}
- return outPos;
+ } else {
+ return inPos;
+ }
}
vec4 main(vec2 coord) {
- // Normalize SKSL pixel coordinate into a unit vector
- float inU = coord.x / viewportWidth;
- float inV = coord.y / viewportHeight;
+ float inU = coord.x;
+ float inV = coord.y;
float outU;
float outV;
- float stretchIntensity;
- // Add the normalized scroll position within scrolling list
+
inU += uScrollX;
inV += uScrollY;
- outU = inU;
- outV = inV;
outU = computeOverscroll(
inU,
uOverscrollX,
@@ -168,7 +166,8 @@
uInverseDistanceStretchedX,
uDistanceStretchedX,
uDistDiffX,
- uInterpolationStrength
+ uInterpolationStrength,
+ viewportWidth
);
outV = computeOverscroll(
inV,
@@ -177,15 +176,15 @@
uInverseDistanceStretchedY,
uDistanceStretchedY,
uDistDiffY,
- uInterpolationStrength
+ uInterpolationStrength,
+ viewportHeight
);
- coord.x = outU * viewportWidth;
- coord.y = outV * viewportHeight;
+ coord.x = outU;
+ coord.y = outV;
return sample(uContentTexture, coord);
})");
static const float ZERO = 0.f;
-static const float CONTENT_DISTANCE_STRETCHED = 1.f;
static const float INTERPOLATION_STRENGTH_VALUE = 0.7f;
sk_sp<SkShader> StretchEffect::getShader(float width, float height,
@@ -196,12 +195,12 @@
float normOverScrollDistX = mStretchDirection.x();
float normOverScrollDistY = mStretchDirection.y();
- float distanceStretchedX = CONTENT_DISTANCE_STRETCHED / (1 + abs(normOverScrollDistX));
- float distanceStretchedY = CONTENT_DISTANCE_STRETCHED / (1 + abs(normOverScrollDistY));
- float inverseDistanceStretchedX = 1.f / CONTENT_DISTANCE_STRETCHED;
- float inverseDistanceStretchedY = 1.f / CONTENT_DISTANCE_STRETCHED;
- float diffX = distanceStretchedX - CONTENT_DISTANCE_STRETCHED;
- float diffY = distanceStretchedY - CONTENT_DISTANCE_STRETCHED;
+ float distanceStretchedX = width / (1 + abs(normOverScrollDistX));
+ float distanceStretchedY = height / (1 + abs(normOverScrollDistY));
+ float inverseDistanceStretchedX = 1.f / width;
+ float inverseDistanceStretchedY = 1.f / height;
+ float diffX = distanceStretchedX - width;
+ float diffY = distanceStretchedY - height;
if (mBuilder == nullptr) {
mBuilder = std::make_unique<SkRuntimeShaderBuilder>(getStretchEffect());
@@ -210,8 +209,8 @@
mBuilder->child("uContentTexture") = snapshotImage->makeShader(
SkTileMode::kClamp, SkTileMode::kClamp, SkSamplingOptions(SkFilterMode::kLinear));
mBuilder->uniform("uInterpolationStrength").set(&INTERPOLATION_STRENGTH_VALUE, 1);
- mBuilder->uniform("uStretchAffectedDistX").set(&CONTENT_DISTANCE_STRETCHED, 1);
- mBuilder->uniform("uStretchAffectedDistY").set(&CONTENT_DISTANCE_STRETCHED, 1);
+ mBuilder->uniform("uStretchAffectedDistX").set(&width, 1);
+ mBuilder->uniform("uStretchAffectedDistY").set(&height, 1);
mBuilder->uniform("uDistanceStretchedX").set(&distanceStretchedX, 1);
mBuilder->uniform("uDistanceStretchedY").set(&distanceStretchedY, 1);
mBuilder->uniform("uInverseDistanceStretchedX").set(&inverseDistanceStretchedX, 1);
diff --git a/libs/hwui/effects/StretchEffect.h b/libs/hwui/effects/StretchEffect.h
index 0e1a654..a92ef5b 100644
--- a/libs/hwui/effects/StretchEffect.h
+++ b/libs/hwui/effects/StretchEffect.h
@@ -111,7 +111,7 @@
bool requiresLayer() const {
return !(isEmpty() ||
- Properties::stretchEffectBehavior == StretchEffectBehavior::UniformScale);
+ Properties::getStretchEffectBehavior() == StretchEffectBehavior::UniformScale);
}
private:
diff --git a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
index dd78d58..82bc5a1 100644
--- a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
+++ b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
@@ -324,6 +324,11 @@
Properties::defaultSdrWhitePoint = sdrWhitePoint;
}
+static void android_view_ThreadedRenderer_setIsHighEndGfx(JNIEnv* env, jobject clazz,
+ jboolean jIsHighEndGfx) {
+ Properties::setIsHighEndGfx(jIsHighEndGfx);
+}
+
static int android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv* env, jobject clazz,
jlong proxyPtr, jlongArray frameInfo, jint frameInfoSize) {
LOG_ALWAYS_FATAL_IF(frameInfoSize != UI_THREAD_FRAME_INFO_SIZE,
@@ -795,6 +800,7 @@
{"nSetOpaque", "(JZ)V", (void*)android_view_ThreadedRenderer_setOpaque},
{"nSetColorMode", "(JI)V", (void*)android_view_ThreadedRenderer_setColorMode},
{"nSetSdrWhitePoint", "(JF)V", (void*)android_view_ThreadedRenderer_setSdrWhitePoint},
+ {"nSetIsHighEndGfx", "(Z)V", (void*)android_view_ThreadedRenderer_setIsHighEndGfx},
{"nSyncAndDrawFrame", "(J[JI)I", (void*)android_view_ThreadedRenderer_syncAndDrawFrame},
{"nDestroy", "(JJ)V", (void*)android_view_ThreadedRenderer_destroy},
{"nRegisterAnimatingRenderNode", "(JJ)V",
diff --git a/libs/hwui/jni/android_graphics_RenderNode.cpp b/libs/hwui/jni/android_graphics_RenderNode.cpp
index a096ed0..002bd83 100644
--- a/libs/hwui/jni/android_graphics_RenderNode.cpp
+++ b/libs/hwui/jni/android_graphics_RenderNode.cpp
@@ -574,7 +574,7 @@
uirenderer::Rect bounds(props.getWidth(), props.getHeight());
bool useStretchShader =
- Properties::stretchEffectBehavior != StretchEffectBehavior::UniformScale;
+ Properties::getStretchEffectBehavior() != StretchEffectBehavior::UniformScale;
if (useStretchShader && info.stretchEffectCount) {
handleStretchEffect(info, bounds);
}
@@ -680,7 +680,8 @@
stretchTargetBounds(*effect, result.width, result.height,
childRelativeBounds,targetBounds);
- if (Properties::stretchEffectBehavior == StretchEffectBehavior::Shader) {
+ if (Properties::getStretchEffectBehavior() ==
+ StretchEffectBehavior::Shader) {
JNIEnv* env = jnienv();
jobject localref = env->NewLocalRef(mWeakRef);
diff --git a/libs/hwui/pipeline/skia/AnimatedDrawables.h b/libs/hwui/pipeline/skia/AnimatedDrawables.h
index 10889e7..d173782 100644
--- a/libs/hwui/pipeline/skia/AnimatedDrawables.h
+++ b/libs/hwui/pipeline/skia/AnimatedDrawables.h
@@ -77,6 +77,7 @@
setUniform(effectBuilder, "in_radius", params.radius);
setUniform(effectBuilder, "in_progress", params.progress);
setUniform(effectBuilder, "in_turbulencePhase", params.turbulencePhase);
+ setUniform(effectBuilder, "in_noisePhase", params.turbulencePhase->value * 0.001);
SkRuntimeShaderBuilder::BuilderUniform uniform = effectBuilder.uniform("in_color");
if (uniform.fVar != nullptr) {
@@ -120,17 +121,24 @@
static constexpr float PI_ROTATE_LEFT = PI * -0.0078125;
static constexpr float SCALE = 1.5;
- static void setUniform(SkRuntimeShaderBuilder& effectBuilder, std::string name,
+ static void setUniform(SkRuntimeShaderBuilder& effectBuilder, const char* name,
sp<uirenderer::CanvasPropertyPrimitive> property) {
- SkRuntimeShaderBuilder::BuilderUniform uniform = effectBuilder.uniform(name.c_str());
+ SkRuntimeShaderBuilder::BuilderUniform uniform = effectBuilder.uniform(name);
if (uniform.fVar != nullptr) {
uniform = property->value;
}
}
- static void setUniform2f(SkRuntimeShaderBuilder& effectBuilder, std::string name, float a,
+ static void setUniform(SkRuntimeShaderBuilder& effectBuilder, const char* name, float value) {
+ SkRuntimeShaderBuilder::BuilderUniform uniform = effectBuilder.uniform(name);
+ if (uniform.fVar != nullptr) {
+ uniform = value;
+ }
+ }
+
+ static void setUniform2f(SkRuntimeShaderBuilder& effectBuilder, const char* name, float a,
float b) {
- SkRuntimeShaderBuilder::BuilderUniform uniform = effectBuilder.uniform(name.c_str());
+ SkRuntimeShaderBuilder::BuilderUniform uniform = effectBuilder.uniform(name);
if (uniform.fVar != nullptr) {
uniform = SkV2{a, b};
}
diff --git a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
index 1c5515c7d..c8247e7 100644
--- a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
+++ b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
@@ -248,7 +248,7 @@
const StretchEffect& stretch = properties.layerProperties().getStretchEffect();
if (stretch.isEmpty() ||
- Properties::stretchEffectBehavior == StretchEffectBehavior::UniformScale) {
+ Properties::getStretchEffectBehavior() == StretchEffectBehavior::UniformScale) {
// If we don't have any stretch effects, issue the filtered
// canvas draw calls to make sure we still punch a hole
// with the same canvas transformation + clip into the target
@@ -327,7 +327,7 @@
canvas->concat(*properties.getTransformMatrix());
}
}
- if (Properties::stretchEffectBehavior == StretchEffectBehavior::UniformScale) {
+ if (Properties::getStretchEffectBehavior() == StretchEffectBehavior::UniformScale) {
const StretchEffect& stretch = properties.layerProperties().getStretchEffect();
if (!stretch.isEmpty()) {
canvas->concat(
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index bae1ab5..c1f61e08 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -195,6 +195,10 @@
auto funcs = mRenderThread.getASurfaceControlFunctions();
+ if (surfaceControl == nullptr) {
+ setASurfaceTransactionCallback(nullptr);
+ }
+
if (mSurfaceControl != nullptr) {
funcs.unregisterListenerFunc(this, &onSurfaceStatsAvailable);
funcs.releaseFunc(mSurfaceControl);
@@ -673,20 +677,8 @@
}
if (frameInfo != nullptr) {
- if (gpuCompleteTime == -1) {
- gpuCompleteTime = frameInfo->get(FrameInfoIndex::SwapBuffersCompleted);
- }
- if (gpuCompleteTime < frameInfo->get(FrameInfoIndex::IssueDrawCommandsStart)) {
- // On Vulkan the GPU commands are flushed to the GPU during IssueDrawCommands rather
- // than after SwapBuffers. So if the GPU signals before issue draw commands, then
- // something probably went wrong. Anything after that could just be expected
- // pipeline differences
- ALOGW("Impossible GPU complete time issueCommandsStart=%" PRIi64
- " gpuComplete=%" PRIi64,
- frameInfo->get(FrameInfoIndex::IssueDrawCommandsStart), gpuCompleteTime);
- gpuCompleteTime = frameInfo->get(FrameInfoIndex::SwapBuffersCompleted);
- }
- frameInfo->set(FrameInfoIndex::FrameCompleted) = gpuCompleteTime;
+ frameInfo->set(FrameInfoIndex::FrameCompleted) = std::max(gpuCompleteTime,
+ frameInfo->get(FrameInfoIndex::SwapBuffersCompleted));
frameInfo->set(FrameInfoIndex::GpuCompleted) = gpuCompleteTime;
instance->mJankTracker.finishFrame(*frameInfo, instance->mFrameMetricsReporter);
}
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index 0112686..07146e8 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -340,6 +340,8 @@
}
void VulkanManager::initialize() {
+ std::lock_guard _lock{mInitializeLock};
+
if (mDevice != VK_NULL_HANDLE) {
return;
}
diff --git a/libs/hwui/renderthread/VulkanManager.h b/libs/hwui/renderthread/VulkanManager.h
index 7b5fe19..b816649 100644
--- a/libs/hwui/renderthread/VulkanManager.h
+++ b/libs/hwui/renderthread/VulkanManager.h
@@ -220,6 +220,8 @@
VkSemaphore mSwapSemaphore = VK_NULL_HANDLE;
void* mDestroySemaphoreContext = nullptr;
+
+ std::mutex mInitializeLock;
};
} /* namespace renderthread */
diff --git a/libs/hwui/renderthread/VulkanSurface.cpp b/libs/hwui/renderthread/VulkanSurface.cpp
index 474d2cc..c559425 100644
--- a/libs/hwui/renderthread/VulkanSurface.cpp
+++ b/libs/hwui/renderthread/VulkanSurface.cpp
@@ -329,20 +329,16 @@
if (bufferInfo.buffer.get() != nullptr && bufferInfo.dequeued) {
int err = mNativeWindow->cancelBuffer(mNativeWindow.get(), bufferInfo.buffer.get(),
- bufferInfo.dequeue_fence);
+ bufferInfo.dequeue_fence.release());
if (err != 0) {
ALOGE("cancelBuffer[%u] failed during destroy: %s (%d)", i, strerror(-err), err);
}
bufferInfo.dequeued = false;
-
- if (bufferInfo.dequeue_fence >= 0) {
- close(bufferInfo.dequeue_fence);
- bufferInfo.dequeue_fence = -1;
- }
+ bufferInfo.dequeue_fence.reset();
}
LOG_ALWAYS_FATAL_IF(bufferInfo.dequeued);
- LOG_ALWAYS_FATAL_IF(bufferInfo.dequeue_fence != -1);
+ LOG_ALWAYS_FATAL_IF(bufferInfo.dequeue_fence.ok());
bufferInfo.skSurface.reset();
bufferInfo.buffer.clear();
@@ -365,8 +361,12 @@
// Since auto pre-rotation is enabled, dequeueBuffer to get the consumer driven buffer size
// from ANativeWindowBuffer.
ANativeWindowBuffer* buffer;
- int fence_fd;
- err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buffer, &fence_fd);
+ base::unique_fd fence_fd;
+ {
+ int rawFd = -1;
+ err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buffer, &rawFd);
+ fence_fd.reset(rawFd);
+ }
if (err != 0) {
ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), err);
return nullptr;
@@ -387,7 +387,7 @@
if (err != 0) {
ALOGE("native_window_set_buffers_transform(%d) failed: %s (%d)", transformHint,
strerror(-err), err);
- mNativeWindow->cancelBuffer(mNativeWindow.get(), buffer, fence_fd);
+ mNativeWindow->cancelBuffer(mNativeWindow.get(), buffer, fence_fd.release());
return nullptr;
}
mWindowInfo.transform = transformHint;
@@ -405,19 +405,19 @@
for (idx = 0; idx < mWindowInfo.bufferCount; idx++) {
if (mNativeBuffers[idx].buffer.get() == buffer) {
mNativeBuffers[idx].dequeued = true;
- mNativeBuffers[idx].dequeue_fence = fence_fd;
+ mNativeBuffers[idx].dequeue_fence = std::move(fence_fd);
break;
} else if (mNativeBuffers[idx].buffer.get() == nullptr) {
// increasing the number of buffers we have allocated
mNativeBuffers[idx].buffer = buffer;
mNativeBuffers[idx].dequeued = true;
- mNativeBuffers[idx].dequeue_fence = fence_fd;
+ mNativeBuffers[idx].dequeue_fence = std::move(fence_fd);
break;
}
}
if (idx == mWindowInfo.bufferCount) {
ALOGE("dequeueBuffer returned unrecognized buffer");
- mNativeWindow->cancelBuffer(mNativeWindow.get(), buffer, fence_fd);
+ mNativeWindow->cancelBuffer(mNativeWindow.get(), buffer, fence_fd.release());
return nullptr;
}
@@ -429,7 +429,7 @@
kTopLeft_GrSurfaceOrigin, mWindowInfo.colorspace, nullptr);
if (bufferInfo->skSurface.get() == nullptr) {
ALOGE("SkSurface::MakeFromAHardwareBuffer failed");
- mNativeWindow->cancelBuffer(mNativeWindow.get(), buffer, fence_fd);
+ mNativeWindow->cancelBuffer(mNativeWindow.get(), buffer, fence_fd.release());
return nullptr;
}
}
@@ -460,25 +460,23 @@
LOG_ALWAYS_FATAL_IF(!mCurrentBufferInfo);
VulkanSurface::NativeBufferInfo& currentBuffer = *mCurrentBufferInfo;
- int queuedFd = (semaphoreFd != -1) ? semaphoreFd : currentBuffer.dequeue_fence;
+ // queueBuffer always closes fence, even on error
+ int queuedFd = (semaphoreFd != -1) ? semaphoreFd : currentBuffer.dequeue_fence.release();
int err = mNativeWindow->queueBuffer(mNativeWindow.get(), currentBuffer.buffer.get(), queuedFd);
currentBuffer.dequeued = false;
- // queueBuffer always closes fence, even on error
if (err != 0) {
ALOGE("queueBuffer failed: %s (%d)", strerror(-err), err);
+ // cancelBuffer takes ownership of the fence
mNativeWindow->cancelBuffer(mNativeWindow.get(), currentBuffer.buffer.get(),
- currentBuffer.dequeue_fence);
+ currentBuffer.dequeue_fence.release());
} else {
currentBuffer.hasValidContents = true;
currentBuffer.lastPresentedCount = mPresentCount;
mPresentCount++;
}
- if (currentBuffer.dequeue_fence >= 0) {
- close(currentBuffer.dequeue_fence);
- currentBuffer.dequeue_fence = -1;
- }
+ currentBuffer.dequeue_fence.reset();
return err == 0;
}
diff --git a/libs/hwui/renderthread/VulkanSurface.h b/libs/hwui/renderthread/VulkanSurface.h
index 7c25545..beb71b72 100644
--- a/libs/hwui/renderthread/VulkanSurface.h
+++ b/libs/hwui/renderthread/VulkanSurface.h
@@ -15,6 +15,7 @@
*/
#pragma once
+#include <android-base/unique_fd.h>
#include <system/graphics.h>
#include <system/window.h>
#include <vulkan/vulkan.h>
@@ -57,7 +58,7 @@
// -1 any other time. When valid, we own the fd, and must ensure it is
// closed: either by closing it explicitly when queueing the buffer,
// or by passing ownership e.g. to ANativeWindow::cancelBuffer().
- int dequeue_fence = -1;
+ base::unique_fd dequeue_fence;
bool dequeued = false;
uint32_t lastPresentedCount = 0;
bool hasValidContents = false;
diff --git a/libs/hwui/tests/common/TestUtils.h b/libs/hwui/tests/common/TestUtils.h
index cf8fc82..5092675 100644
--- a/libs/hwui/tests/common/TestUtils.h
+++ b/libs/hwui/tests/common/TestUtils.h
@@ -287,6 +287,7 @@
int sync = 0;
int contextDestroyed = 0;
int destroyed = 0;
+ int removeOverlays = 0;
int glesDraw = 0;
};
@@ -311,6 +312,12 @@
expectOnRenderThread("onDestroyed");
sMockFunctorCounts[functor].destroyed++;
},
+ .removeOverlays =
+ [](int functor, void* data,
+ void (*mergeTransaction)(ASurfaceTransaction*)) {
+ expectOnRenderThread("removeOverlays");
+ sMockFunctorCounts[functor].removeOverlays++;
+ },
};
switch (mode) {
case RenderMode::OpenGL_ES:
diff --git a/libs/hwui/tests/common/scenes/StretchyListViewAnimation.cpp b/libs/hwui/tests/common/scenes/StretchyListViewAnimation.cpp
index c451112..e677549 100644
--- a/libs/hwui/tests/common/scenes/StretchyListViewAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/StretchyListViewAnimation.cpp
@@ -186,7 +186,7 @@
void doFrame(int frameNr) override {
if (frameNr == 0) {
- Properties::stretchEffectBehavior = stretchBehavior();
+ Properties::setStretchEffectBehavior(stretchBehavior());
if (forceLayer()) {
mListView->mutateStagingProperties().mutateLayerProperties().setType(
LayerType::RenderLayer);
diff --git a/libs/hwui/tests/unit/main.cpp b/libs/hwui/tests/unit/main.cpp
index 402cb58..10c874e 100644
--- a/libs/hwui/tests/unit/main.cpp
+++ b/libs/hwui/tests/unit/main.cpp
@@ -62,8 +62,10 @@
gSigChain.insert(pair<int, struct sigaction>(sig, old_sa));
}
- // Replace the default GLES driver
+ // Avoid talking to SF
Properties::isolatedProcess = true;
+ // Default to GLES (Vulkan-aware tests will override this)
+ Properties::overrideRenderPipelineType(RenderPipelineType::SkiaGL);
// Run the tests
testing::InitGoogleTest(&argc, argv);
diff --git a/location/java/android/location/SatellitePvt.java b/location/java/android/location/SatellitePvt.java
index 1456f74..bb9ae6e 100644
--- a/location/java/android/location/SatellitePvt.java
+++ b/location/java/android/location/SatellitePvt.java
@@ -45,8 +45,41 @@
*/
@SystemApi
public final class SatellitePvt implements Parcelable {
+ /**
+ * Bit mask for {@link #mFlags} indicating valid satellite position, velocity and clock info
+ * fields are stored in the SatellitePvt.
+ */
+ private static final int HAS_POSITION_VELOCITY_CLOCK_INFO = 1 << 0;
+
+ /**
+ * Bit mask for {@link #mFlags} indicating a valid iono delay field is stored in the
+ * SatellitePvt.
+ */
+ private static final int HAS_IONO = 1 << 1;
+
+ /**
+ * Bit mask for {@link #mFlags} indicating a valid tropo delay field is stored in the
+ * SatellitePvt.
+ */
+ private static final int HAS_TROPO = 1 << 2;
+
+ /**
+ * A bitfield of flags indicating the validity of the fields in this SatellitePvt.
+ * The bit masks are defined in the constants with prefix HAS_*
+ *
+ * <p>Fields for which there is no corresponding flag must be filled in with a valid value.
+ * For convenience, these are marked as mandatory.
+ *
+ * <p>Others fields may have invalid information in them, if not marked as valid by the
+ * corresponding bit in flags.
+ */
+ private final int mFlags;
+
+ @Nullable
private final PositionEcef mPositionEcef;
+ @Nullable
private final VelocityEcef mVelocityEcef;
+ @Nullable
private final ClockInfo mClockInfo;
private final double mIonoDelayMeters;
private final double mTropoDelayMeters;
@@ -351,20 +384,13 @@
}
private SatellitePvt(
- @NonNull PositionEcef positionEcef,
- @NonNull VelocityEcef velocityEcef,
- @NonNull ClockInfo clockInfo,
+ int flags,
+ @Nullable PositionEcef positionEcef,
+ @Nullable VelocityEcef velocityEcef,
+ @Nullable ClockInfo clockInfo,
double ionoDelayMeters,
double tropoDelayMeters) {
- if (positionEcef == null) {
- throw new IllegalArgumentException("Position Ecef cannot be null.");
- }
- if (velocityEcef == null) {
- throw new IllegalArgumentException("Velocity Ecef cannot be null.");
- }
- if (clockInfo == null) {
- throw new IllegalArgumentException("Clock Info cannot be null.");
- }
+ mFlags = flags;
mPositionEcef = positionEcef;
mVelocityEcef = velocityEcef;
mClockInfo = clockInfo;
@@ -373,10 +399,17 @@
}
/**
+ * Gets a bitmask of fields present in this object
+ */
+ public int getFlags() {
+ return mFlags;
+ }
+
+ /**
* Returns a {@link PositionEcef} object that contains estimates of the satellite
* position fields in ECEF coordinate frame.
*/
- @NonNull
+ @Nullable
public PositionEcef getPositionEcef() {
return mPositionEcef;
}
@@ -385,7 +418,7 @@
* Returns a {@link VelocityEcef} object that contains estimates of the satellite
* velocity fields in the ECEF coordinate frame.
*/
- @NonNull
+ @Nullable
public VelocityEcef getVelocityEcef() {
return mVelocityEcef;
}
@@ -394,7 +427,7 @@
* Returns a {@link ClockInfo} object that contains estimates of the satellite
* clock info.
*/
- @NonNull
+ @Nullable
public ClockInfo getClockInfo() {
return mClockInfo;
}
@@ -415,11 +448,29 @@
return mTropoDelayMeters;
}
+ /** Returns {@code true} if {@link #getPositionEcef()}, {@link #getVelocityEcef()},
+ * and {@link #getClockInfo()} are valid.
+ */
+ public boolean hasPositionVelocityClockInfo() {
+ return (mFlags & HAS_POSITION_VELOCITY_CLOCK_INFO) != 0;
+ }
+
+ /** Returns {@code true} if {@link #getIonoDelayMeters()} is valid. */
+ public boolean hasIono() {
+ return (mFlags & HAS_IONO) != 0;
+ }
+
+ /** Returns {@code true} if {@link #getTropoDelayMeters()} is valid. */
+ public boolean hasTropo() {
+ return (mFlags & HAS_TROPO) != 0;
+ }
+
public static final @android.annotation.NonNull Creator<SatellitePvt> CREATOR =
new Creator<SatellitePvt>() {
@Override
@Nullable
public SatellitePvt createFromParcel(Parcel in) {
+ int flags = in.readInt();
ClassLoader classLoader = getClass().getClassLoader();
PositionEcef positionEcef = in.readParcelable(classLoader);
VelocityEcef velocityEcef = in.readParcelable(classLoader);
@@ -428,6 +479,7 @@
double tropoDelayMeters = in.readDouble();
return new SatellitePvt(
+ flags,
positionEcef,
velocityEcef,
clockInfo,
@@ -448,6 +500,7 @@
@Override
public void writeToParcel(@NonNull Parcel parcel, int flags) {
+ parcel.writeInt(mFlags);
parcel.writeParcelable(mPositionEcef, flags);
parcel.writeParcelable(mVelocityEcef, flags);
parcel.writeParcelable(mClockInfo, flags);
@@ -458,7 +511,8 @@
@Override
public String toString() {
return "SatellitePvt{"
- + "PositionEcef=" + mPositionEcef
+ + "Flags=" + mFlags
+ + ", PositionEcef=" + mPositionEcef
+ ", VelocityEcef=" + mVelocityEcef
+ ", ClockInfo=" + mClockInfo
+ ", IonoDelayMeters=" + mIonoDelayMeters
@@ -470,13 +524,30 @@
* Builder class for SatellitePvt.
*/
public static final class Builder {
- private PositionEcef mPositionEcef;
- private VelocityEcef mVelocityEcef;
- private ClockInfo mClockInfo;
+ /**
+ * For documentation of below fields, see corresponding fields in {@link
+ * SatellitePvt}.
+ */
+ private int mFlags;
+ @Nullable private PositionEcef mPositionEcef;
+ @Nullable private VelocityEcef mVelocityEcef;
+ @Nullable private ClockInfo mClockInfo;
private double mIonoDelayMeters;
private double mTropoDelayMeters;
/**
+ * Sets a bitmask of fields present in this object
+ *
+ * @param flags int flags
+ * @return Builder builder object
+ */
+ @NonNull
+ public Builder setFlags(int flags) {
+ mFlags = flags;
+ return this;
+ }
+
+ /**
* Set position ECEF.
*
* @param positionEcef position ECEF object
@@ -546,7 +617,7 @@
*/
@NonNull
public SatellitePvt build() {
- return new SatellitePvt(mPositionEcef, mVelocityEcef, mClockInfo,
+ return new SatellitePvt(mFlags, mPositionEcef, mVelocityEcef, mClockInfo,
mIonoDelayMeters, mTropoDelayMeters);
}
}
diff --git a/native/webview/plat_support/draw_functor.cpp b/native/webview/plat_support/draw_functor.cpp
index ea57ea0..472e0a4 100644
--- a/native/webview/plat_support/draw_functor.cpp
+++ b/native/webview/plat_support/draw_functor.cpp
@@ -192,44 +192,43 @@
int CreateFunctor_v3(void* data, int version,
AwDrawFnFunctorCallbacks* functor_callbacks) {
- static bool callbacks_initialized = false;
- static uirenderer::WebViewFunctorCallbacks webview_functor_callbacks = {
- .onSync = &onSync,
- .onContextDestroyed = &onContextDestroyed,
- .onDestroyed = &onDestroyed,
- .removeOverlays = &removeOverlays,
- };
- if (!callbacks_initialized) {
- switch (uirenderer::WebViewFunctor_queryPlatformRenderMode()) {
- case uirenderer::RenderMode::OpenGL_ES:
- webview_functor_callbacks.gles.draw = &draw_gl;
- break;
- case uirenderer::RenderMode::Vulkan:
- webview_functor_callbacks.vk.initialize = &initializeVk;
- webview_functor_callbacks.vk.draw = &drawVk;
- webview_functor_callbacks.vk.postDraw = &postDrawVk;
- break;
+ static uirenderer::WebViewFunctorCallbacks webview_functor_callbacks = [] {
+ uirenderer::WebViewFunctorCallbacks ret = {
+ .onSync = &onSync,
+ .onContextDestroyed = &onContextDestroyed,
+ .onDestroyed = &onDestroyed,
+ .removeOverlays = &removeOverlays,
+ };
+ switch (uirenderer::WebViewFunctor_queryPlatformRenderMode()) {
+ case uirenderer::RenderMode::OpenGL_ES:
+ ret.gles.draw = &draw_gl;
+ break;
+ case uirenderer::RenderMode::Vulkan:
+ ret.vk.initialize = &initializeVk;
+ ret.vk.draw = &drawVk;
+ ret.vk.postDraw = &postDrawVk;
+ break;
+ }
+ return ret;
+ }();
+ SupportData* support = new SupportData{
+ .data = data,
+ };
+
+ // These callbacks are available on all versions.
+ support->callbacks = {
+ .on_sync = functor_callbacks->on_sync,
+ .on_context_destroyed = functor_callbacks->on_context_destroyed,
+ .on_destroyed = functor_callbacks->on_destroyed,
+ .draw_gl = functor_callbacks->draw_gl,
+ .init_vk = functor_callbacks->init_vk,
+ .draw_vk = functor_callbacks->draw_vk,
+ .post_draw_vk = functor_callbacks->post_draw_vk,
+ };
+
+ if (version >= 3) {
+ support->callbacks.remove_overlays = functor_callbacks->remove_overlays;
}
- callbacks_initialized = true;
- }
- SupportData* support = new SupportData{
- .data = data,
- };
-
- // These callbacks are available on all versions.
- support->callbacks = {
- .on_sync = functor_callbacks->on_sync,
- .on_context_destroyed = functor_callbacks->on_context_destroyed,
- .on_destroyed = functor_callbacks->on_destroyed,
- .draw_gl = functor_callbacks->draw_gl,
- .init_vk = functor_callbacks->init_vk,
- .draw_vk = functor_callbacks->draw_vk,
- .post_draw_vk = functor_callbacks->post_draw_vk,
- };
-
- if (version >= 3) {
- support->callbacks.remove_overlays = functor_callbacks->remove_overlays;
- }
int functor = uirenderer::WebViewFunctor_create(
support, webview_functor_callbacks,
diff --git a/packages/CompanionDeviceManager/res/values-ar/strings.xml b/packages/CompanionDeviceManager/res/values-ar/strings.xml
index 7dd62f6..c3f1e73 100644
--- a/packages/CompanionDeviceManager/res/values-ar/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ar/strings.xml
@@ -20,7 +20,7 @@
<string name="chooser_title" msgid="2262294130493605839">"اختَر <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ليديره تطبيق <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"جهاز"</string>
<string name="profile_name_watch" msgid="576290739483672360">"ساعة"</string>
- <string name="confirmation_title" msgid="8455544820286920304">"السماح لـ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> بإدارة جهاز <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> لديك"</string>
+ <string name="confirmation_title" msgid="8455544820286920304">"السماح للتطبيق <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> بإدارة <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_summary" msgid="2059360676631420073">"هذا التطبيق مطلوب لإدارة <xliff:g id="PROFILE_NAME">%1$s</xliff:g>. <xliff:g id="PRIVILEGES_DISCPLAIMER">%2$s</xliff:g>"</string>
<string name="consent_yes" msgid="8344487259618762872">"السماح"</string>
<string name="consent_no" msgid="2640796915611404382">"عدم السماح"</string>
diff --git a/packages/CompanionDeviceManager/res/values-ur/strings.xml b/packages/CompanionDeviceManager/res/values-ur/strings.xml
index 88c8a4b..ee79921 100644
--- a/packages/CompanionDeviceManager/res/values-ur/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ur/strings.xml
@@ -20,7 +20,7 @@
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> کے ذریعے نظم کئے جانے کیلئے <xliff:g id="PROFILE_NAME">%1$s</xliff:g> کو منتخب کریں"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"آلہ"</string>
<string name="profile_name_watch" msgid="576290739483672360">"دیکھیں"</string>
- <string name="confirmation_title" msgid="8455544820286920304">"اپنے <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> کا نظم کرنے کے لیے <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> کو اجازت دیں"</string>
+ <string name="confirmation_title" msgid="8455544820286920304">"اپنے <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> کا نظم کرنے کے لیے <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> کو اجازت دیں"</string>
<string name="profile_summary" msgid="2059360676631420073">"اس ایپ کو آپ کے <xliff:g id="PROFILE_NAME">%1$s</xliff:g> کا نظم کرنے کی ضرورت ہے۔ <xliff:g id="PRIVILEGES_DISCPLAIMER">%2$s</xliff:g>"</string>
<string name="consent_yes" msgid="8344487259618762872">"اجازت دیں"</string>
<string name="consent_no" msgid="2640796915611404382">"اجازت نہ دیں"</string>
diff --git a/packages/Connectivity/framework/Android.bp b/packages/Connectivity/framework/Android.bp
index a75792c..6eb8348 100644
--- a/packages/Connectivity/framework/Android.bp
+++ b/packages/Connectivity/framework/Android.bp
@@ -59,6 +59,22 @@
],
}
+java_library {
+ name: "framework-connectivity-annotations",
+ sdk_version: "module_current",
+ srcs: [
+ "src/android/net/ConnectivityAnnotations.java",
+ ],
+ libs: [
+ "framework-annotations-lib",
+ "framework-connectivity",
+ ],
+ visibility: [
+ "//frameworks/base:__subpackages__",
+ "//packages/modules/Connectivity:__subpackages__",
+ ],
+}
+
java_sdk_library {
name: "framework-connectivity",
sdk_version: "module_current",
diff --git a/packages/Connectivity/framework/api/current.txt b/packages/Connectivity/framework/api/current.txt
index 13ecb12..33f4d14 100644
--- a/packages/Connectivity/framework/api/current.txt
+++ b/packages/Connectivity/framework/api/current.txt
@@ -70,7 +70,7 @@
method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.Network getActiveNetwork();
method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.NetworkInfo getActiveNetworkInfo();
method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.NetworkInfo[] getAllNetworkInfo();
- method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.Network[] getAllNetworks();
+ method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.Network[] getAllNetworks();
method @Deprecated public boolean getBackgroundDataSetting();
method @Nullable public android.net.Network getBoundNetworkForProcess();
method public int getConnectionOwnerUid(int, @NonNull java.net.InetSocketAddress, @NonNull java.net.InetSocketAddress);
@@ -406,6 +406,7 @@
method @NonNull public android.net.NetworkRequest.Builder clearCapabilities();
method public android.net.NetworkRequest.Builder removeCapability(int);
method public android.net.NetworkRequest.Builder removeTransportType(int);
+ method @NonNull public android.net.NetworkRequest.Builder setIncludeOtherUidNetworks(boolean);
method @Deprecated public android.net.NetworkRequest.Builder setNetworkSpecifier(String);
method public android.net.NetworkRequest.Builder setNetworkSpecifier(android.net.NetworkSpecifier);
}
diff --git a/packages/Connectivity/framework/api/module-lib-current.txt b/packages/Connectivity/framework/api/module-lib-current.txt
index b219375..6c454bc 100644
--- a/packages/Connectivity/framework/api/module-lib-current.txt
+++ b/packages/Connectivity/framework/api/module-lib-current.txt
@@ -48,6 +48,7 @@
public class ConnectivitySettingsManager {
method public static void clearGlobalProxy(@NonNull android.content.Context);
+ method @NonNull public static java.util.Set<java.lang.String> getAppsAllowedOnRestrictedNetworks(@NonNull android.content.Context);
method @Nullable public static String getCaptivePortalHttpUrl(@NonNull android.content.Context);
method public static int getCaptivePortalMode(@NonNull android.content.Context, int);
method @NonNull public static java.time.Duration getConnectivityKeepPendingIntentDuration(@NonNull android.content.Context, @NonNull java.time.Duration);
@@ -65,9 +66,9 @@
method @NonNull public static String getPrivateDnsDefaultMode(@NonNull android.content.Context);
method @Nullable public static String getPrivateDnsHostname(@NonNull android.content.Context);
method public static int getPrivateDnsMode(@NonNull android.content.Context);
- method @NonNull public static java.util.Set<java.lang.String> getRestrictedAllowedApps(@NonNull android.content.Context);
method public static boolean getWifiAlwaysRequested(@NonNull android.content.Context, boolean);
method @NonNull public static java.time.Duration getWifiDataActivityTimeout(@NonNull android.content.Context, @NonNull java.time.Duration);
+ method public static void setAppsAllowedOnRestrictedNetworks(@NonNull android.content.Context, @NonNull java.util.Set<java.lang.String>);
method public static void setCaptivePortalHttpUrl(@NonNull android.content.Context, @Nullable String);
method public static void setCaptivePortalMode(@NonNull android.content.Context, int);
method public static void setConnectivityKeepPendingIntentDuration(@NonNull android.content.Context, @NonNull java.time.Duration);
@@ -85,7 +86,6 @@
method public static void setPrivateDnsDefaultMode(@NonNull android.content.Context, @NonNull int);
method public static void setPrivateDnsHostname(@NonNull android.content.Context, @Nullable String);
method public static void setPrivateDnsMode(@NonNull android.content.Context, int);
- method public static void setRestrictedAllowedApps(@NonNull android.content.Context, @NonNull java.util.Set<java.lang.String>);
method public static void setWifiAlwaysRequested(@NonNull android.content.Context, boolean);
method public static void setWifiDataActivityTimeout(@NonNull android.content.Context, @NonNull java.time.Duration);
field public static final int CAPTIVE_PORTAL_MODE_AVOID = 2; // 0x2
diff --git a/packages/Connectivity/framework/api/system-current.txt b/packages/Connectivity/framework/api/system-current.txt
index 52673c9..d1d51da 100644
--- a/packages/Connectivity/framework/api/system-current.txt
+++ b/packages/Connectivity/framework/api/system-current.txt
@@ -296,7 +296,6 @@
method @NonNull public android.net.NetworkCapabilities.Builder addCapability(int);
method @NonNull public android.net.NetworkCapabilities.Builder addTransportType(int);
method @NonNull public android.net.NetworkCapabilities build();
- method @NonNull public android.net.NetworkCapabilities.Builder clearAll();
method @NonNull public android.net.NetworkCapabilities.Builder removeCapability(int);
method @NonNull public android.net.NetworkCapabilities.Builder removeTransportType(int);
method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setAdministratorUids(@NonNull int[]);
@@ -310,6 +309,7 @@
method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setSsid(@Nullable String);
method @NonNull public android.net.NetworkCapabilities.Builder setSubscriptionIds(@NonNull java.util.Set<java.lang.Integer>);
method @NonNull public android.net.NetworkCapabilities.Builder setTransportInfo(@Nullable android.net.TransportInfo);
+ method @NonNull public static android.net.NetworkCapabilities.Builder withoutDefaultCapabilities();
}
public class NetworkProvider {
@@ -398,6 +398,7 @@
public abstract class QosFilter {
method @NonNull public abstract android.net.Network getNetwork();
method public abstract boolean matchesLocalAddress(@NonNull java.net.InetAddress, int, int);
+ method public abstract boolean matchesRemoteAddress(@NonNull java.net.InetAddress, int, int);
}
public final class QosSession implements android.os.Parcelable {
@@ -420,6 +421,7 @@
method public int describeContents();
method @NonNull public java.net.InetSocketAddress getLocalSocketAddress();
method @NonNull public android.net.Network getNetwork();
+ method @Nullable public java.net.InetSocketAddress getRemoteSocketAddress();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.QosSocketInfo> CREATOR;
}
diff --git a/packages/Connectivity/framework/src/android/net/ConnectivityAnnotations.java b/packages/Connectivity/framework/src/android/net/ConnectivityAnnotations.java
new file mode 100644
index 0000000..eb1faa0
--- /dev/null
+++ b/packages/Connectivity/framework/src/android/net/ConnectivityAnnotations.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Type annotations for constants used in the connectivity API surface.
+ *
+ * The annotations are maintained in a separate class so that it can be built as
+ * a separate library that other modules can build against, as Typedef should not
+ * be exposed as SystemApi.
+ *
+ * @hide
+ */
+public final class ConnectivityAnnotations {
+ private ConnectivityAnnotations() {}
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(flag = true, value = {
+ ConnectivityManager.MULTIPATH_PREFERENCE_HANDOVER,
+ ConnectivityManager.MULTIPATH_PREFERENCE_RELIABILITY,
+ ConnectivityManager.MULTIPATH_PREFERENCE_PERFORMANCE,
+ })
+ public @interface MultipathPreference {}
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(flag = false, value = {
+ ConnectivityManager.RESTRICT_BACKGROUND_STATUS_DISABLED,
+ ConnectivityManager.RESTRICT_BACKGROUND_STATUS_WHITELISTED,
+ ConnectivityManager.RESTRICT_BACKGROUND_STATUS_ENABLED,
+ })
+ public @interface RestrictBackgroundStatus {}
+}
diff --git a/packages/Connectivity/framework/src/android/net/ConnectivityManager.java b/packages/Connectivity/framework/src/android/net/ConnectivityManager.java
index df81603..93455bc 100644
--- a/packages/Connectivity/framework/src/android/net/ConnectivityManager.java
+++ b/packages/Connectivity/framework/src/android/net/ConnectivityManager.java
@@ -40,6 +40,8 @@
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.net.ConnectivityAnnotations.MultipathPreference;
+import android.net.ConnectivityAnnotations.RestrictBackgroundStatus;
import android.net.ConnectivityDiagnosticsManager.DataStallReport.DetectionMethod;
import android.net.IpSecManager.UdpEncapsulationSocket;
import android.net.SocketKeepalive.Callback;
@@ -1431,10 +1433,18 @@
* Returns an array of all {@link Network} currently tracked by the
* framework.
*
+ * @deprecated This method does not provide any notification of network state changes, forcing
+ * apps to call it repeatedly. This is inefficient and prone to race conditions.
+ * Apps should use methods such as
+ * {@link #registerNetworkCallback(NetworkRequest, NetworkCallback)} instead.
+ * Apps that desire to obtain information about networks that do not apply to them
+ * can use {@link NetworkRequest.Builder#setIncludeOtherUidNetworks}.
+ *
* @return an array of {@link Network} objects.
*/
@RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
@NonNull
+ @Deprecated
public Network[] getAllNetworks() {
try {
return mService.getAllNetworks();
@@ -4799,16 +4809,6 @@
MULTIPATH_PREFERENCE_RELIABILITY |
MULTIPATH_PREFERENCE_PERFORMANCE;
- /** @hide */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(flag = true, value = {
- MULTIPATH_PREFERENCE_HANDOVER,
- MULTIPATH_PREFERENCE_RELIABILITY,
- MULTIPATH_PREFERENCE_PERFORMANCE,
- })
- public @interface MultipathPreference {
- }
-
/**
* Provides a hint to the calling application on whether it is desirable to use the
* multinetwork APIs (e.g., {@link Network#openConnection}, {@link Network#bindSocket}, etc.)
@@ -5030,16 +5030,6 @@
public static final String ACTION_RESTRICT_BACKGROUND_CHANGED =
"android.net.conn.RESTRICT_BACKGROUND_CHANGED";
- /** @hide */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(flag = false, value = {
- RESTRICT_BACKGROUND_STATUS_DISABLED,
- RESTRICT_BACKGROUND_STATUS_WHITELISTED,
- RESTRICT_BACKGROUND_STATUS_ENABLED,
- })
- public @interface RestrictBackgroundStatus {
- }
-
/**
* Determines if the calling application is subject to metered network restrictions while
* running on background.
diff --git a/packages/Connectivity/framework/src/android/net/ConnectivitySettingsManager.java b/packages/Connectivity/framework/src/android/net/ConnectivitySettingsManager.java
index 07754e4..1a69099 100644
--- a/packages/Connectivity/framework/src/android/net/ConnectivitySettingsManager.java
+++ b/packages/Connectivity/framework/src/android/net/ConnectivitySettingsManager.java
@@ -27,7 +27,7 @@
import android.annotation.SystemApi;
import android.content.ContentResolver;
import android.content.Context;
-import android.net.ConnectivityManager.MultipathPreference;
+import android.net.ConnectivityAnnotations.MultipathPreference;
import android.os.Process;
import android.os.UserHandle;
import android.provider.Settings;
@@ -43,7 +43,6 @@
import java.util.List;
import java.util.Set;
import java.util.StringJoiner;
-import java.util.regex.Pattern;
/**
* A manager class for connectivity module settings.
@@ -375,11 +374,12 @@
private static final String PRIVATE_DNS_MODE_PROVIDER_HOSTNAME_STRING = "hostname";
/**
- * A list of apps that should be granted netd system permission for using restricted networks.
+ * A list of apps that is allowed on restricted networks.
*
* @hide
*/
- public static final String RESTRICTED_ALLOWED_APPS = "restricted_allowed_apps";
+ public static final String APPS_ALLOWED_ON_RESTRICTED_NETWORKS =
+ "apps_allowed_on_restricted_networks";
/**
* Get mobile data activity timeout from {@link Settings}.
@@ -1047,17 +1047,16 @@
}
/**
- * Get the list of apps(from {@link Settings}) that should be granted netd system permission for
- * using restricted networks.
+ * Get the list of apps(from {@link Settings}) that is allowed on restricted networks.
*
* @param context The {@link Context} to query the setting.
- * @return A list of apps that should be granted netd system permission for using restricted
- * networks or null if no setting value.
+ * @return A list of apps that is allowed on restricted networks or null if no setting
+ * value.
*/
@NonNull
- public static Set<String> getRestrictedAllowedApps(@NonNull Context context) {
+ public static Set<String> getAppsAllowedOnRestrictedNetworks(@NonNull Context context) {
final String appList = Settings.Secure.getString(
- context.getContentResolver(), RESTRICTED_ALLOWED_APPS);
+ context.getContentResolver(), APPS_ALLOWED_ON_RESTRICTED_NETWORKS);
if (TextUtils.isEmpty(appList)) {
return new ArraySet<>();
}
@@ -1065,27 +1064,24 @@
}
/**
- * Set the list of apps(from {@link Settings}) that should be granted netd system permission for
- * using restricted networks.
+ * Set the list of apps(from {@link Settings}) that is allowed on restricted networks.
*
* Note: Please refer to android developer guidelines for valid app(package name).
* https://developer.android.com/guide/topics/manifest/manifest-element.html#package
*
* @param context The {@link Context} to set the setting.
- * @param list A list of apps that should be granted netd system permission for using
- * restricted networks.
+ * @param list A list of apps that is allowed on restricted networks.
*/
- public static void setRestrictedAllowedApps(@NonNull Context context,
+ public static void setAppsAllowedOnRestrictedNetworks(@NonNull Context context,
@NonNull Set<String> list) {
- final Pattern appPattern = Pattern.compile("[a-zA-Z_0-9]+([.][a-zA-Z_0-9]+)*");
final StringJoiner joiner = new StringJoiner(";");
for (String app : list) {
- if (!appPattern.matcher(app).matches()) {
+ if (app == null || app.contains(";")) {
throw new IllegalArgumentException("Invalid app(package name)");
}
joiner.add(app);
}
- Settings.Secure.putString(
- context.getContentResolver(), RESTRICTED_ALLOWED_APPS, joiner.toString());
+ Settings.Secure.putString(context.getContentResolver(), APPS_ALLOWED_ON_RESTRICTED_NETWORKS,
+ joiner.toString());
}
}
diff --git a/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java b/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java
index 2e4d8f8..4932952 100644
--- a/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java
+++ b/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java
@@ -2416,6 +2416,11 @@
return mTransportInfo.getApplicableRedactions();
}
+ private NetworkCapabilities removeDefaultCapabilites() {
+ mNetworkCapabilities &= ~DEFAULT_CAPABILITIES;
+ return this;
+ }
+
/**
* Builder class for NetworkCapabilities.
*
@@ -2452,6 +2457,16 @@
}
/**
+ * Creates a new Builder without the default capabilities.
+ */
+ @NonNull
+ public static Builder withoutDefaultCapabilities() {
+ final NetworkCapabilities nc = new NetworkCapabilities();
+ nc.removeDefaultCapabilites();
+ return new Builder(nc);
+ }
+
+ /**
* Adds the given transport type.
*
* Multiple transports may be added. Note that when searching for a network to satisfy a
@@ -2512,17 +2527,6 @@
}
/**
- * Completely clears the contents of this object, removing even the capabilities that are
- * set by default when the object is constructed.
- * @return this builder
- */
- @NonNull
- public Builder clearAll() {
- mCaps.clearAll();
- return this;
- }
-
- /**
* Sets the owner UID.
*
* The default value is {@link Process#INVALID_UID}. Pass this value to reset.
diff --git a/packages/Connectivity/framework/src/android/net/NetworkRequest.java b/packages/Connectivity/framework/src/android/net/NetworkRequest.java
index a384109..afc76d6 100644
--- a/packages/Connectivity/framework/src/android/net/NetworkRequest.java
+++ b/packages/Connectivity/framework/src/android/net/NetworkRequest.java
@@ -200,8 +200,9 @@
private final NetworkCapabilities mNetworkCapabilities;
- // A boolean that represents the user modified NOT_VCN_MANAGED capability.
- private boolean mModifiedNotVcnManaged = false;
+ // A boolean that represents whether the NOT_VCN_MANAGED capability should be deduced when
+ // the NetworkRequest object is built.
+ private boolean mShouldDeduceNotVcnManaged = true;
/**
* Default constructor for Builder.
@@ -223,7 +224,7 @@
// If the caller constructed the builder from a request, it means the user
// might explicitly want the capabilities from the request. Thus, the NOT_VCN_MANAGED
// capabilities should not be touched later.
- mModifiedNotVcnManaged = true;
+ mShouldDeduceNotVcnManaged = false;
}
/**
@@ -254,7 +255,7 @@
public Builder addCapability(@NetworkCapabilities.NetCapability int capability) {
mNetworkCapabilities.addCapability(capability);
if (capability == NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED) {
- mModifiedNotVcnManaged = true;
+ mShouldDeduceNotVcnManaged = false;
}
return this;
}
@@ -268,7 +269,7 @@
public Builder removeCapability(@NetworkCapabilities.NetCapability int capability) {
mNetworkCapabilities.removeCapability(capability);
if (capability == NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED) {
- mModifiedNotVcnManaged = true;
+ mShouldDeduceNotVcnManaged = false;
}
return this;
}
@@ -287,10 +288,15 @@
}
/**
- * Set the watched UIDs for this request. This will be reset and wiped out unless
- * the calling app holds the CHANGE_NETWORK_STATE permission.
+ * Sets this request to match only networks that apply to the specified UIDs.
*
- * @param uids The watched UIDs as a set of {@code Range<Integer>}, or null for everything.
+ * By default, the set of UIDs is the UID of the calling app, and this request will match
+ * any network that applies to the app. Setting it to {@code null} will observe any
+ * network on the system, even if it does not apply to this app. In this case, any
+ * {@link NetworkSpecifier} set on this request will be redacted or removed to prevent the
+ * application deducing restricted information such as location.
+ *
+ * @param uids The UIDs as a set of {@code Range<Integer>}, or null for everything.
* @return The builder to facilitate chaining.
* @hide
*/
@@ -352,7 +358,7 @@
mNetworkCapabilities.clearAll();
// If the caller explicitly clear all capabilities, the NOT_VCN_MANAGED capabilities
// should not be add back later.
- mModifiedNotVcnManaged = true;
+ mShouldDeduceNotVcnManaged = false;
return this;
}
@@ -453,6 +459,9 @@
throw new IllegalArgumentException("A MatchAllNetworkSpecifier is not permitted");
}
mNetworkCapabilities.setNetworkSpecifier(networkSpecifier);
+ // Do not touch NOT_VCN_MANAGED if the caller needs to access to a very specific
+ // Network.
+ mShouldDeduceNotVcnManaged = false;
return this;
}
@@ -486,12 +495,13 @@
* {@link #VCN_SUPPORTED_CAPABILITIES}, add the NET_CAPABILITY_NOT_VCN_MANAGED to
* allow the callers automatically utilize VCN networks if available.
* 2. For the requests that explicitly add or remove NET_CAPABILITY_NOT_VCN_MANAGED,
+ * or has clear intention of tracking specific network,
* do not alter them to allow user fire request that suits their need.
*
* @hide
*/
private void deduceNotVcnManagedCapability(final NetworkCapabilities nc) {
- if (mModifiedNotVcnManaged) return;
+ if (!mShouldDeduceNotVcnManaged) return;
for (final int cap : nc.getCapabilities()) {
if (!VCN_SUPPORTED_CAPABILITIES.contains(cap)) return;
}
@@ -517,6 +527,30 @@
mNetworkCapabilities.setSubscriptionIds(subIds);
return this;
}
+
+ /**
+ * Specifies whether the built request should also match networks that do not apply to the
+ * calling UID.
+ *
+ * By default, the built request will only match networks that apply to the calling UID.
+ * If this method is called with {@code true}, the built request will match any network on
+ * the system that matches the other parameters of the request. In this case, any
+ * information in the built request that is subject to redaction for security or privacy
+ * purposes, such as a {@link NetworkSpecifier}, will be redacted or removed to prevent the
+ * application deducing sensitive information.
+ *
+ * @param include Whether to match networks that do not apply to the calling UID.
+ * @return The builder to facilitate chaining.
+ */
+ @NonNull
+ public Builder setIncludeOtherUidNetworks(boolean include) {
+ if (include) {
+ mNetworkCapabilities.setUids(null);
+ } else {
+ mNetworkCapabilities.setSingleUid(Process.myUid());
+ }
+ return this;
+ }
}
// implement the Parcelable interface
diff --git a/packages/Connectivity/framework/src/android/net/QosFilter.java b/packages/Connectivity/framework/src/android/net/QosFilter.java
index ab55002..957c867 100644
--- a/packages/Connectivity/framework/src/android/net/QosFilter.java
+++ b/packages/Connectivity/framework/src/android/net/QosFilter.java
@@ -71,5 +71,16 @@
*/
public abstract boolean matchesLocalAddress(@NonNull InetAddress address,
int startPort, int endPort);
+
+ /**
+ * Determines whether or not the parameters is a match for the filter.
+ *
+ * @param address the remote address
+ * @param startPort the start of the port range
+ * @param endPort the end of the port range
+ * @return whether the parameters match the remote address of the filter
+ */
+ public abstract boolean matchesRemoteAddress(@NonNull InetAddress address,
+ int startPort, int endPort);
}
diff --git a/packages/Connectivity/framework/src/android/net/QosSocketFilter.java b/packages/Connectivity/framework/src/android/net/QosSocketFilter.java
index 2080e68..69da7f4 100644
--- a/packages/Connectivity/framework/src/android/net/QosSocketFilter.java
+++ b/packages/Connectivity/framework/src/android/net/QosSocketFilter.java
@@ -138,13 +138,26 @@
if (mQosSocketInfo.getLocalSocketAddress() == null) {
return false;
}
-
- return matchesLocalAddress(mQosSocketInfo.getLocalSocketAddress(), address, startPort,
+ return matchesAddress(mQosSocketInfo.getLocalSocketAddress(), address, startPort,
endPort);
}
/**
- * Called from {@link QosSocketFilter#matchesLocalAddress(InetAddress, int, int)} with the
+ * @inheritDoc
+ */
+ @Override
+ public boolean matchesRemoteAddress(@NonNull final InetAddress address, final int startPort,
+ final int endPort) {
+ if (mQosSocketInfo.getRemoteSocketAddress() == null) {
+ return false;
+ }
+ return matchesAddress(mQosSocketInfo.getRemoteSocketAddress(), address, startPort,
+ endPort);
+ }
+
+ /**
+ * Called from {@link QosSocketFilter#matchesLocalAddress(InetAddress, int, int)}
+ * and {@link QosSocketFilter#matchesRemoteAddress(InetAddress, int, int)} with the
* filterSocketAddress coming from {@link QosSocketInfo#getLocalSocketAddress()}.
* <p>
* This method exists for testing purposes since {@link QosSocketInfo} couldn't be mocked
@@ -156,7 +169,7 @@
* @param endPort the end of the port range to check
*/
@VisibleForTesting
- public static boolean matchesLocalAddress(@NonNull final InetSocketAddress filterSocketAddress,
+ public static boolean matchesAddress(@NonNull final InetSocketAddress filterSocketAddress,
@NonNull final InetAddress address,
final int startPort, final int endPort) {
return startPort <= filterSocketAddress.getPort()
diff --git a/packages/Connectivity/framework/src/android/net/QosSocketInfo.java b/packages/Connectivity/framework/src/android/net/QosSocketInfo.java
index 53d9669..a45d507 100644
--- a/packages/Connectivity/framework/src/android/net/QosSocketInfo.java
+++ b/packages/Connectivity/framework/src/android/net/QosSocketInfo.java
@@ -17,6 +17,7 @@
package android.net;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.ParcelFileDescriptor;
@@ -32,7 +33,8 @@
/**
* Used in conjunction with
* {@link ConnectivityManager#registerQosCallback}
- * in order to receive Qos Sessions related to the local address and port of a bound {@link Socket}.
+ * in order to receive Qos Sessions related to the local address and port of a bound {@link Socket}
+ * and/or remote address and port of a connected {@link Socket}.
*
* @hide
*/
@@ -48,6 +50,9 @@
@NonNull
private final InetSocketAddress mLocalSocketAddress;
+ @Nullable
+ private final InetSocketAddress mRemoteSocketAddress;
+
/**
* The {@link Network} the socket is on.
*
@@ -81,6 +86,18 @@
}
/**
+ * The remote address of the socket passed into {@link QosSocketInfo(Network, Socket)}.
+ * The value does not reflect any changes that occur to the socket after it is first set
+ * in the constructor.
+ *
+ * @return the remote address of the socket if socket is connected, null otherwise
+ */
+ @Nullable
+ public InetSocketAddress getRemoteSocketAddress() {
+ return mRemoteSocketAddress;
+ }
+
+ /**
* Creates a {@link QosSocketInfo} given a {@link Network} and bound {@link Socket}. The
* {@link Socket} must remain bound in order to receive {@link QosSession}s.
*
@@ -95,6 +112,12 @@
mParcelFileDescriptor = ParcelFileDescriptor.fromSocket(socket);
mLocalSocketAddress =
new InetSocketAddress(socket.getLocalAddress(), socket.getLocalPort());
+
+ if (socket.isConnected()) {
+ mRemoteSocketAddress = (InetSocketAddress) socket.getRemoteSocketAddress();
+ } else {
+ mRemoteSocketAddress = null;
+ }
}
/* Parcelable methods */
@@ -102,11 +125,15 @@
mNetwork = Objects.requireNonNull(Network.CREATOR.createFromParcel(in));
mParcelFileDescriptor = ParcelFileDescriptor.CREATOR.createFromParcel(in);
- final int addressLength = in.readInt();
- mLocalSocketAddress = readSocketAddress(in, addressLength);
+ final int localAddressLength = in.readInt();
+ mLocalSocketAddress = readSocketAddress(in, localAddressLength);
+
+ final int remoteAddressLength = in.readInt();
+ mRemoteSocketAddress = remoteAddressLength == 0 ? null
+ : readSocketAddress(in, remoteAddressLength);
}
- private InetSocketAddress readSocketAddress(final Parcel in, final int addressLength) {
+ private @NonNull InetSocketAddress readSocketAddress(final Parcel in, final int addressLength) {
final byte[] address = new byte[addressLength];
in.readByteArray(address);
final int port = in.readInt();
@@ -130,10 +157,19 @@
mNetwork.writeToParcel(dest, 0);
mParcelFileDescriptor.writeToParcel(dest, 0);
- final byte[] address = mLocalSocketAddress.getAddress().getAddress();
- dest.writeInt(address.length);
- dest.writeByteArray(address);
+ final byte[] localAddress = mLocalSocketAddress.getAddress().getAddress();
+ dest.writeInt(localAddress.length);
+ dest.writeByteArray(localAddress);
dest.writeInt(mLocalSocketAddress.getPort());
+
+ if (mRemoteSocketAddress == null) {
+ dest.writeInt(0);
+ } else {
+ final byte[] remoteAddress = mRemoteSocketAddress.getAddress().getAddress();
+ dest.writeInt(remoteAddress.length);
+ dest.writeByteArray(remoteAddress);
+ dest.writeInt(mRemoteSocketAddress.getPort());
+ }
}
@NonNull
diff --git a/packages/Connectivity/framework/src/android/net/apf/ApfCapabilities.java b/packages/Connectivity/framework/src/android/net/apf/ApfCapabilities.java
index 85b24713..663c1b3 100644
--- a/packages/Connectivity/framework/src/android/net/apf/ApfCapabilities.java
+++ b/packages/Connectivity/framework/src/android/net/apf/ApfCapabilities.java
@@ -131,43 +131,21 @@
* @return Whether the APF Filter in the device should filter out IEEE 802.3 Frames.
*/
public static boolean getApfDrop8023Frames() {
- // TODO(b/183076074): remove reading resources from system resources
+ // TODO: deprecate/remove this method (now unused in the platform), as the resource was
+ // moved to NetworkStack.
final Resources systemRes = Resources.getSystem();
final int id = systemRes.getIdentifier("config_apfDrop802_3Frames", "bool", "android");
return systemRes.getBoolean(id);
}
/**
- * @return Whether the APF Filter in the device should filter out IEEE 802.3 Frames.
- * @hide
- */
- public static boolean getApfDrop8023Frames(@NonNull Context context) {
- final ConnectivityResources res = getResources(context);
- // TODO(b/183076074): use R.bool.config_apfDrop802_3Frames directly
- final int id = res.get().getIdentifier("config_apfDrop802_3Frames", "bool",
- res.getResourcesContext().getPackageName());
- return res.get().getBoolean(id);
- }
-
- /**
* @return An array of denylisted EtherType, packets with EtherTypes within it will be dropped.
*/
public static @NonNull int[] getApfEtherTypeBlackList() {
- // TODO(b/183076074): remove reading resources from system resources
+ // TODO: deprecate/remove this method (now unused in the platform), as the resource was
+ // moved to NetworkStack.
final Resources systemRes = Resources.getSystem();
final int id = systemRes.getIdentifier("config_apfEthTypeBlackList", "array", "android");
return systemRes.getIntArray(id);
}
-
- /**
- * @return An array of denylisted EtherType, packets with EtherTypes within it will be dropped.
- * @hide
- */
- public static @NonNull int[] getApfEtherTypeDenyList(@NonNull Context context) {
- final ConnectivityResources res = getResources(context);
- // TODO(b/183076074): use R.array.config_apfEthTypeDenyList directly
- final int id = res.get().getIdentifier("config_apfEthTypeDenyList", "array",
- res.getResourcesContext().getPackageName());
- return res.get().getIntArray(id);
- }
}
diff --git a/packages/Connectivity/service/Android.bp b/packages/Connectivity/service/Android.bp
index 813a239..7265426 100644
--- a/packages/Connectivity/service/Android.bp
+++ b/packages/Connectivity/service/Android.bp
@@ -65,6 +65,7 @@
"stable.core.platform.api.stubs",
"android_system_server_stubs_current",
"framework-annotations-lib",
+ "framework-connectivity-annotations",
"framework-connectivity.impl",
"framework-tethering.stubs.module_lib",
"framework-wifi.stubs.module_lib",
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values/config.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values/config.xml
index 82d8e4f..70ddb9a 100644
--- a/packages/Connectivity/service/ServiceConnectivityResources/res/values/config.xml
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values/config.xml
@@ -52,22 +52,6 @@
<item>12,60000</item><!-- mobile_cbs -->
</string-array>
- <!-- Whether the APF Filter in the device should filter out IEEE 802.3 Frames
- Those frames are identified by the field Eth-type having values
- less than 0x600 -->
- <bool translatable="false" name="config_apfDrop802_3Frames">true</bool>
-
- <!-- An array of Denylisted EtherType, packets with EtherTypes within this array
- will be dropped
- TODO: need to put proper values, these are for testing purposes only -->
- <integer-array translatable="false" name="config_apfEthTypeDenyList">
- <item>0x88A2</item>
- <item>0x88A4</item>
- <item>0x88B8</item>
- <item>0x88CD</item>
- <item>0x88E3</item>
- </integer-array>
-
<!-- Default supported concurrent socket keepalive slots per transport type, used by
ConnectivityManager.createSocketKeepalive() for calculating the number of keepalive
offload slots that should be reserved for privileged access. This string array should be
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values/overlayable.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values/overlayable.xml
index 568deca..fd23566 100644
--- a/packages/Connectivity/service/ServiceConnectivityResources/res/values/overlayable.xml
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values/overlayable.xml
@@ -21,8 +21,6 @@
<item type="string" name="config_networkCaptivePortalServerUrl"/>
<item type="integer" name="config_networkTransitionTimeout"/>
<item type="array" name="config_wakeonlan_supported_interfaces"/>
- <item type="bool" name="config_apfDrop802_3Frames"/>
- <item type="array" name="config_apfEthTypeDenyList"/>
<item type="integer" name="config_networkMeteredMultipathPreference"/>
<item type="array" name="config_networkSupportedKeepaliveCount"/>
<item type="integer" name="config_networkAvoidBadWifi"/>
diff --git a/packages/Connectivity/service/src/com/android/server/ConnectivityService.java b/packages/Connectivity/service/src/com/android/server/ConnectivityService.java
index ed2fe82..6027a99 100644
--- a/packages/Connectivity/service/src/com/android/server/ConnectivityService.java
+++ b/packages/Connectivity/service/src/com/android/server/ConnectivityService.java
@@ -105,12 +105,12 @@
import android.net.CaptivePortal;
import android.net.CaptivePortalData;
import android.net.ConnectionInfo;
+import android.net.ConnectivityAnnotations.RestrictBackgroundStatus;
import android.net.ConnectivityDiagnosticsManager.ConnectivityReport;
import android.net.ConnectivityDiagnosticsManager.DataStallReport;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.BlockedReason;
import android.net.ConnectivityManager.NetworkCallback;
-import android.net.ConnectivityManager.RestrictBackgroundStatus;
import android.net.ConnectivityResources;
import android.net.ConnectivitySettingsManager;
import android.net.DataStallReportParcelable;
@@ -1045,14 +1045,10 @@
} else {
// ConnectivityService publishes binder service using publishBinderService() with
// no priority assigned will be treated as NORMAL priority. Dumpsys does not send
- // "--dump-priority" arguments to the service. Thus, dump both NORMAL and HIGH to
- // align the legacy design.
+ // "--dump-priority" arguments to the service. Thus, dump NORMAL only to align the
+ // legacy output for dumpsys connectivity.
// TODO: Integrate into signal dump.
dumpNormal(fd, pw, args);
- pw.println();
- pw.println("DUMP OF SERVICE HIGH connectivity");
- pw.println();
- dumpHigh(fd, pw);
}
}
}
@@ -1395,7 +1391,7 @@
// arguments like the handler or the DnsResolver.
// TODO : remove this ; it is probably better handled with a sentinel request.
mNoServiceNetwork = new NetworkAgentInfo(null,
- new Network(NO_SERVICE_NET_ID),
+ new Network(INetd.UNREACHABLE_NET_ID),
new NetworkInfo(TYPE_NONE, 0, "", ""),
new LinkProperties(), new NetworkCapabilities(),
new NetworkScore.Builder().setLegacyInt(0).build(), mContext, null,
@@ -1501,12 +1497,7 @@
ConnectivitySettingsManager.WIFI_ALWAYS_REQUESTED, false /* defaultValue */);
final boolean vehicleAlwaysRequested = mResources.get().getBoolean(
R.bool.config_vehicleInternalNetworkAlwaysRequested);
- // TODO (b/183076074): remove legacy fallback after migrating overlays
- final boolean legacyAlwaysRequested = mContext.getResources().getBoolean(
- mContext.getResources().getIdentifier(
- "config_vehicleInternalNetworkAlwaysRequested", "bool", "android"));
- handleAlwaysOnNetworkRequest(mDefaultVehicleRequest,
- vehicleAlwaysRequested || legacyAlwaysRequested);
+ handleAlwaysOnNetworkRequest(mDefaultVehicleRequest, vehicleAlwaysRequested);
}
private void registerSettingsCallbacks() {
@@ -2156,10 +2147,22 @@
private void restrictRequestUidsForCallerAndSetRequestorInfo(NetworkCapabilities nc,
int callerUid, String callerPackageName) {
+ // There is no need to track the effective UID of the request here. If the caller
+ // lacks the settings permission, the effective UID is the same as the calling ID.
if (!checkSettingsPermission()) {
- // There is no need to track the effective UID of the request here. If the caller lacks
- // the settings permission, the effective UID is the same as the calling ID.
- nc.setSingleUid(callerUid);
+ // Unprivileged apps can only pass in null or their own UID.
+ if (nc.getUids() == null) {
+ // If the caller passes in null, the callback will also match networks that do not
+ // apply to its UID, similarly to what it would see if it called getAllNetworks.
+ // In this case, redact everything in the request immediately. This ensures that the
+ // app is not able to get any redacted information by filing an unredacted request
+ // and observing whether the request matches something.
+ if (nc.getNetworkSpecifier() != null) {
+ nc.setNetworkSpecifier(nc.getNetworkSpecifier().redact());
+ }
+ } else {
+ nc.setSingleUid(callerUid);
+ }
}
nc.setRequestorUidAndPackageName(callerUid, callerPackageName);
nc.setAdministratorUids(new int[0]);
@@ -2210,7 +2213,7 @@
@NonNull
public List<NetworkStateSnapshot> getAllNetworkStateSnapshots() {
// This contains IMSI details, so make sure the caller is privileged.
- PermissionUtils.enforceNetworkStackPermission(mContext);
+ enforceNetworkStackOrSettingsPermission();
final ArrayList<NetworkStateSnapshot> result = new ArrayList<>();
for (Network network : getAllNetworks()) {
@@ -6466,8 +6469,6 @@
// Request used to optionally keep vehicle internal network always active
private final NetworkRequest mDefaultVehicleRequest;
- // TODO replace with INetd.UNREACHABLE_NET_ID when available.
- private static final int NO_SERVICE_NET_ID = 52;
// Sentinel NAI used to direct apps with default networks that should have no connectivity to a
// network with no service. This NAI should never be matched against, nor should any public API
// ever return the associated network. For this reason, this NAI is not in the list of available
@@ -6817,14 +6818,6 @@
int mark = mResources.get().getInteger(R.integer.config_networkWakeupPacketMark);
int mask = mResources.get().getInteger(R.integer.config_networkWakeupPacketMask);
- // TODO (b/183076074): remove legacy fallback after migrating overlays
- final int legacyMark = mContext.getResources().getInteger(mContext.getResources()
- .getIdentifier("config_networkWakeupPacketMark", "integer", "android"));
- final int legacyMask = mContext.getResources().getInteger(mContext.getResources()
- .getIdentifier("config_networkWakeupPacketMask", "integer", "android"));
- mark = mark == 0 ? legacyMark : mark;
- mask = mask == 0 ? legacyMask : mask;
-
// Mask/mark of zero will not detect anything interesting.
// Don't install rules unless both values are nonzero.
if (mark == 0 || mask == 0) {
@@ -8578,11 +8571,7 @@
final UnderlyingNetworkInfo[] underlyingNetworkInfos = getAllVpnInfo();
try {
final ArrayList<NetworkStateSnapshot> snapshots = new ArrayList<>();
- // TODO: Directly use NetworkStateSnapshot when feasible.
- for (final NetworkState state : getAllNetworkState()) {
- final NetworkStateSnapshot snapshot = new NetworkStateSnapshot(state.network,
- state.networkCapabilities, state.linkProperties, state.subscriberId,
- state.legacyNetworkType);
+ for (final NetworkStateSnapshot snapshot : getAllNetworkStateSnapshots()) {
snapshots.add(snapshot);
}
mStatsManager.notifyNetworkStatus(getDefaultNetworks(),
diff --git a/packages/Connectivity/service/src/com/android/server/connectivity/KeepaliveTracker.java b/packages/Connectivity/service/src/com/android/server/connectivity/KeepaliveTracker.java
index acf39f0..7d922a4 100644
--- a/packages/Connectivity/service/src/com/android/server/connectivity/KeepaliveTracker.java
+++ b/packages/Connectivity/service/src/com/android/server/connectivity/KeepaliveTracker.java
@@ -114,18 +114,11 @@
mContext = context;
mSupportedKeepalives = KeepaliveUtils.getSupportedKeepalives(mContext);
- // TODO (b/183076074): stop reading legacy resources after migrating overlays
- final int legacyReservedSlots = mContext.getResources().getInteger(
- mContext.getResources().getIdentifier(
- "config_reservedPrivilegedKeepaliveSlots", "integer", "android"));
- final int legacyAllowedSlots = mContext.getResources().getInteger(
- mContext.getResources().getIdentifier(
- "config_allowedUnprivilegedKeepalivePerUid", "integer", "android"));
final ConnectivityResources res = new ConnectivityResources(mContext);
- mReservedPrivilegedSlots = Math.min(legacyReservedSlots, res.get().getInteger(
- R.integer.config_reservedPrivilegedKeepaliveSlots));
- mAllowedUnprivilegedSlotsForUid = Math.min(legacyAllowedSlots, res.get().getInteger(
- R.integer.config_allowedUnprivilegedKeepalivePerUid));
+ mReservedPrivilegedSlots = res.get().getInteger(
+ R.integer.config_reservedPrivilegedKeepaliveSlots);
+ mAllowedUnprivilegedSlotsForUid = res.get().getInteger(
+ R.integer.config_allowedUnprivilegedKeepalivePerUid);
}
/**
diff --git a/packages/Connectivity/service/src/com/android/server/connectivity/NetworkRanker.java b/packages/Connectivity/service/src/com/android/server/connectivity/NetworkRanker.java
index e839837..d7eb9c8 100644
--- a/packages/Connectivity/service/src/com/android/server/connectivity/NetworkRanker.java
+++ b/packages/Connectivity/service/src/com/android/server/connectivity/NetworkRanker.java
@@ -108,7 +108,58 @@
}
}
- @Nullable private <T extends Scoreable> T getBestNetworkByPolicy(
+ private <T extends Scoreable> boolean isBadWiFi(@NonNull final T candidate) {
+ return candidate.getScore().hasPolicy(POLICY_EVER_VALIDATED_NOT_AVOIDED_WHEN_BAD)
+ && candidate.getCapsNoCopy().hasTransport(TRANSPORT_WIFI);
+ }
+
+ /**
+ * Apply the "yield to bad WiFi" policy.
+ *
+ * This function must run immediately after the validation policy.
+ *
+ * If any of the accepted networks has the "yield to bad WiFi" policy AND there are some
+ * bad WiFis in the rejected list, then move the networks with the policy to the rejected
+ * list. If this leaves no accepted network, then move the bad WiFis back to the accepted list.
+ *
+ * This function returns nothing, but will have updated accepted and rejected in-place.
+ *
+ * @param accepted networks accepted by the validation policy
+ * @param rejected networks rejected by the validation policy
+ */
+ private <T extends Scoreable> void applyYieldToBadWifiPolicy(@NonNull ArrayList<T> accepted,
+ @NonNull ArrayList<T> rejected) {
+ if (!CollectionUtils.any(accepted, n -> n.getScore().hasPolicy(POLICY_YIELD_TO_BAD_WIFI))) {
+ // No network with the policy : do nothing.
+ return;
+ }
+ if (!CollectionUtils.any(rejected, n -> isBadWiFi(n))) {
+ // No bad WiFi : do nothing.
+ return;
+ }
+ if (CollectionUtils.all(accepted, n -> n.getScore().hasPolicy(POLICY_YIELD_TO_BAD_WIFI))) {
+ // All validated networks yield to bad WiFis : keep bad WiFis alongside with the
+ // yielders. This is important because the yielders need to be compared to the bad
+ // wifis by the following policies (e.g. exiting).
+ final ArrayList<T> acceptedYielders = new ArrayList<>(accepted);
+ final ArrayList<T> rejectedWithBadWiFis = new ArrayList<>(rejected);
+ partitionInto(rejectedWithBadWiFis, n -> isBadWiFi(n), accepted, rejected);
+ accepted.addAll(acceptedYielders);
+ return;
+ }
+ // Only some of the validated networks yield to bad WiFi : keep only the ones who don't.
+ final ArrayList<T> acceptedWithYielders = new ArrayList<>(accepted);
+ partitionInto(acceptedWithYielders, n -> !n.getScore().hasPolicy(POLICY_YIELD_TO_BAD_WIFI),
+ accepted, rejected);
+ }
+
+ /**
+ * Get the best network among a list of candidates according to policy.
+ * @param candidates the candidates
+ * @param currentSatisfier the current satisfier, or null if none
+ * @return the best network
+ */
+ @Nullable public <T extends Scoreable> T getBestNetworkByPolicy(
@NonNull List<T> candidates,
@Nullable final T currentSatisfier) {
// Used as working areas.
@@ -148,24 +199,15 @@
if (accepted.size() == 1) return accepted.get(0);
if (accepted.size() > 0 && rejected.size() > 0) candidates = new ArrayList<>(accepted);
- // Yield to bad wifi policy : if any wifi has ever been validated (even if it's now
- // unvalidated), and unless it's been explicitly avoided when bad in UI, then keep only
- // networks that don't yield to such a wifi network.
- final boolean anyWiFiEverValidated = CollectionUtils.any(candidates,
- nai -> nai.getScore().hasPolicy(POLICY_EVER_VALIDATED_NOT_AVOIDED_WHEN_BAD)
- && nai.getCapsNoCopy().hasTransport(TRANSPORT_WIFI));
- if (anyWiFiEverValidated) {
- partitionInto(candidates, nai -> !nai.getScore().hasPolicy(POLICY_YIELD_TO_BAD_WIFI),
- accepted, rejected);
- if (accepted.size() == 1) return accepted.get(0);
- if (accepted.size() > 0 && rejected.size() > 0) candidates = new ArrayList<>(accepted);
- }
-
// If any network is validated (or should be accepted even if it's not validated), then
// don't choose one that isn't.
partitionInto(candidates, nai -> nai.getScore().hasPolicy(POLICY_IS_VALIDATED)
|| nai.getScore().hasPolicy(POLICY_ACCEPT_UNVALIDATED),
accepted, rejected);
+ // Yield to bad wifi policy : if any network has the "yield to bad WiFi" policy and
+ // there are bad WiFis connected, then accept the bad WiFis and reject the networks with
+ // the policy.
+ applyYieldToBadWifiPolicy(accepted, rejected);
if (accepted.size() == 1) return accepted.get(0);
if (accepted.size() > 0 && rejected.size() > 0) candidates = new ArrayList<>(accepted);
@@ -194,16 +236,26 @@
// subscription with the same transport.
partitionInto(candidates, nai -> nai.getScore().hasPolicy(POLICY_TRANSPORT_PRIMARY),
accepted, rejected);
- for (final Scoreable defaultSubNai : accepted) {
- // Remove all networks without the DEFAULT_SUBSCRIPTION policy and the same transports
- // as a network that has it.
- final int[] transports = defaultSubNai.getCapsNoCopy().getTransportTypes();
- candidates.removeIf(nai -> !nai.getScore().hasPolicy(POLICY_TRANSPORT_PRIMARY)
- && Arrays.equals(transports, nai.getCapsNoCopy().getTransportTypes()));
+ if (accepted.size() > 0) {
+ // Some networks are primary for their transport. For each transport, keep only the
+ // primary, but also keep all networks for which there isn't a primary (which are now
+ // in the |rejected| array).
+ // So for each primary network, remove from |rejected| all networks with the same
+ // transports as one of the primary networks. The remaining networks should be accepted.
+ for (final T defaultSubNai : accepted) {
+ final int[] transports = defaultSubNai.getCapsNoCopy().getTransportTypes();
+ rejected.removeIf(
+ nai -> Arrays.equals(transports, nai.getCapsNoCopy().getTransportTypes()));
+ }
+ // Now the |rejected| list contains networks with transports for which there isn't
+ // a primary network. Add them back to the candidates.
+ accepted.addAll(rejected);
+ candidates = new ArrayList<>(accepted);
}
if (1 == candidates.size()) return candidates.get(0);
- // It's guaranteed candidates.size() > 0 because there is at least one with the
- // TRANSPORT_PRIMARY policy and only those without it were removed.
+ // If there were no primary network, then candidates.size() > 0 because it didn't
+ // change from the previous result. If there were, it's guaranteed candidates.size() > 0
+ // because accepted.size() > 0 above.
// If some of the networks have a better transport than others, keep only the ones with
// the best transports.
diff --git a/packages/Connectivity/service/src/com/android/server/connectivity/PermissionMonitor.java b/packages/Connectivity/service/src/com/android/server/connectivity/PermissionMonitor.java
index 5886b1a..9bda59c 100644
--- a/packages/Connectivity/service/src/com/android/server/connectivity/PermissionMonitor.java
+++ b/packages/Connectivity/service/src/com/android/server/connectivity/PermissionMonitor.java
@@ -24,6 +24,7 @@
import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED;
import static android.content.pm.PackageManager.GET_PERMISSIONS;
import static android.content.pm.PackageManager.MATCH_ANY_USER;
+import static android.net.ConnectivitySettingsManager.APPS_ALLOWED_ON_RESTRICTED_NETWORKS;
import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
import static android.os.Process.INVALID_UID;
import static android.os.Process.SYSTEM_UID;
@@ -39,6 +40,8 @@
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.database.ContentObserver;
+import android.net.ConnectivitySettingsManager;
import android.net.INetd;
import android.net.UidRange;
import android.net.Uri;
@@ -48,7 +51,9 @@
import android.os.SystemConfigManager;
import android.os.UserHandle;
import android.os.UserManager;
+import android.provider.Settings;
import android.system.OsConstants;
+import android.util.ArraySet;
import android.util.Log;
import android.util.SparseArray;
import android.util.SparseIntArray;
@@ -66,7 +71,6 @@
import java.util.Map.Entry;
import java.util.Set;
-
/**
* A utility class to inform Netd of UID permisisons.
* Does a mass update at boot and then monitors for app install/remove.
@@ -105,6 +109,14 @@
@GuardedBy("this")
private final Set<Integer> mAllApps = new HashSet<>();
+ // A set of apps which are allowed to use restricted networks. These apps can't hold the
+ // CONNECTIVITY_USE_RESTRICTED_NETWORKS permission because they can't be signature|privileged
+ // apps. However, these apps should still be able to use restricted networks under certain
+ // conditions (e.g. government app using emergency services). So grant netd system permission
+ // to uids whose package name is listed in APPS_ALLOWED_ON_RESTRICTED_NETWORKS setting.
+ @GuardedBy("this")
+ private final Set<String> mAppsAllowedOnRestrictedNetworks = new ArraySet<>();
+
private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -135,6 +147,22 @@
public int getDeviceFirstSdkInt() {
return Build.VERSION.DEVICE_INITIAL_SDK_INT;
}
+
+ /**
+ * Get apps allowed to use restricted networks via ConnectivitySettingsManager.
+ */
+ public Set<String> getAppsAllowedOnRestrictedNetworks(@NonNull Context context) {
+ return ConnectivitySettingsManager.getAppsAllowedOnRestrictedNetworks(context);
+ }
+
+ /**
+ * Register ContentObserver for given Uri.
+ */
+ public void registerContentObserver(@NonNull Context context, @NonNull Uri uri,
+ boolean notifyForDescendants, @NonNull ContentObserver observer) {
+ context.getContentResolver().registerContentObserver(
+ uri, notifyForDescendants, observer);
+ }
}
public PermissionMonitor(@NonNull final Context context, @NonNull final INetd netd) {
@@ -157,14 +185,31 @@
public synchronized void startMonitoring() {
log("Monitoring");
+ final Context userAllContext = mContext.createContextAsUser(UserHandle.ALL, 0 /* flags */);
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
intentFilter.addDataScheme("package");
- mContext.createContextAsUser(UserHandle.ALL, 0 /* flags */).registerReceiver(
+ userAllContext.registerReceiver(
mIntentReceiver, intentFilter, null /* broadcastPermission */,
null /* scheduler */);
+ // Register APPS_ALLOWED_ON_RESTRICTED_NETWORKS setting observer
+ mDeps.registerContentObserver(
+ userAllContext,
+ Settings.Secure.getUriFor(APPS_ALLOWED_ON_RESTRICTED_NETWORKS),
+ false /* notifyForDescendants */,
+ new ContentObserver(null) {
+ @Override
+ public void onChange(boolean selfChange) {
+ onSettingChanged();
+ }
+ });
+
+ // Read APPS_ALLOWED_ON_RESTRICTED_NETWORKS setting and update
+ // mAppsAllowedOnRestrictedNetworks.
+ updateAppsAllowedOnRestrictedNetworks(mDeps.getAppsAllowedOnRestrictedNetworks(mContext));
+
List<PackageInfo> apps = mPackageManager.getInstalledPackages(GET_PERMISSIONS
| MATCH_ANY_USER);
if (apps == null) {
@@ -220,11 +265,33 @@
}
@VisibleForTesting
+ void updateAppsAllowedOnRestrictedNetworks(final Set<String> apps) {
+ mAppsAllowedOnRestrictedNetworks.clear();
+ mAppsAllowedOnRestrictedNetworks.addAll(apps);
+ }
+
+ @VisibleForTesting
static boolean isVendorApp(@NonNull ApplicationInfo appInfo) {
return appInfo.isVendor() || appInfo.isOem() || appInfo.isProduct();
}
@VisibleForTesting
+ boolean isCarryoverPackage(final ApplicationInfo appInfo) {
+ if (appInfo == null) return false;
+ return (appInfo.targetSdkVersion < VERSION_Q && isVendorApp(appInfo))
+ // Backward compatibility for b/114245686, on devices that launched before Q daemons
+ // and apps running as the system UID are exempted from this check.
+ || (appInfo.uid == SYSTEM_UID && mDeps.getDeviceFirstSdkInt() < VERSION_Q);
+ }
+
+ @VisibleForTesting
+ boolean isAppAllowedOnRestrictedNetworks(@NonNull final PackageInfo app) {
+ // Check whether package name is in allowed on restricted networks app list. If so, this app
+ // can have netd system permission.
+ return mAppsAllowedOnRestrictedNetworks.contains(app.packageName);
+ }
+
+ @VisibleForTesting
boolean hasPermission(@NonNull final PackageInfo app, @NonNull final String permission) {
if (app.requestedPermissions == null || app.requestedPermissionsFlags == null) {
return false;
@@ -241,22 +308,10 @@
@VisibleForTesting
boolean hasRestrictedNetworkPermission(@NonNull final PackageInfo app) {
- // TODO : remove this check in the future(b/31479477). All apps should just
- // request the appropriate permission for their use case since android Q.
- if (app.applicationInfo != null) {
- // Backward compatibility for b/114245686, on devices that launched before Q daemons
- // and apps running as the system UID are exempted from this check.
- if (app.applicationInfo.uid == SYSTEM_UID && mDeps.getDeviceFirstSdkInt() < VERSION_Q) {
- return true;
- }
-
- if (app.applicationInfo.targetSdkVersion < VERSION_Q
- && isVendorApp(app.applicationInfo)) {
- return true;
- }
- }
-
- return hasPermission(app, PERMISSION_MAINLINE_NETWORK_STACK)
+ // TODO : remove carryover package check in the future(b/31479477). All apps should just
+ // request the appropriate permission for their use case since android Q.
+ return isCarryoverPackage(app.applicationInfo) || isAppAllowedOnRestrictedNetworks(app)
+ || hasPermission(app, PERMISSION_MAINLINE_NETWORK_STACK)
|| hasPermission(app, NETWORK_STACK)
|| hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS);
}
@@ -410,6 +465,20 @@
mAllApps.add(UserHandle.getAppId(uid));
}
+ private Boolean highestUidNetworkPermission(int uid) {
+ Boolean permission = null;
+ final String[] packages = mPackageManager.getPackagesForUid(uid);
+ if (!CollectionUtils.isEmpty(packages)) {
+ for (String name : packages) {
+ permission = highestPermissionForUid(permission, name);
+ if (permission == SYSTEM) {
+ break;
+ }
+ }
+ }
+ return permission;
+ }
+
/**
* Called when a package is removed.
*
@@ -440,19 +509,14 @@
}
Map<Integer, Boolean> apps = new HashMap<>();
- Boolean permission = null;
- String[] packages = mPackageManager.getPackagesForUid(uid);
- if (packages != null && packages.length > 0) {
- for (String name : packages) {
- permission = highestPermissionForUid(permission, name);
- if (permission == SYSTEM) {
- // An app with this UID still has the SYSTEM permission.
- // Therefore, this UID must already have the SYSTEM permission.
- // Nothing to do.
- return;
- }
- }
+ final Boolean permission = highestUidNetworkPermission(uid);
+ if (permission == SYSTEM) {
+ // An app with this UID still has the SYSTEM permission.
+ // Therefore, this UID must already have the SYSTEM permission.
+ // Nothing to do.
+ return;
}
+
if (permission == mApps.get(uid)) {
// The permissions of this UID have not changed. Nothing to do.
return;
@@ -705,6 +769,38 @@
return mVpnUidRanges.get(iface);
}
+ private synchronized void onSettingChanged() {
+ // Step1. Update apps allowed to use restricted networks and compute the set of packages to
+ // update.
+ final Set<String> packagesToUpdate = new ArraySet<>(mAppsAllowedOnRestrictedNetworks);
+ updateAppsAllowedOnRestrictedNetworks(mDeps.getAppsAllowedOnRestrictedNetworks(mContext));
+ packagesToUpdate.addAll(mAppsAllowedOnRestrictedNetworks);
+
+ final Map<Integer, Boolean> updatedApps = new HashMap<>();
+ final Map<Integer, Boolean> removedApps = new HashMap<>();
+
+ // Step2. For each package to update, find out its new permission.
+ for (String app : packagesToUpdate) {
+ final PackageInfo info = getPackageInfo(app);
+ if (info == null || info.applicationInfo == null) continue;
+
+ final int uid = info.applicationInfo.uid;
+ final Boolean permission = highestUidNetworkPermission(uid);
+
+ if (null == permission) {
+ removedApps.put(uid, NETWORK); // Doesn't matter which permission is set here.
+ mApps.remove(uid);
+ } else {
+ updatedApps.put(uid, permission);
+ mApps.put(uid, permission);
+ }
+ }
+
+ // Step3. Update or revoke permission for uids with netd.
+ update(mUsers, updatedApps, true /* add */);
+ update(mUsers, removedApps, false /* add */);
+ }
+
/** Dump info to dumpsys */
public void dump(IndentingPrintWriter pw) {
pw.println("Interface filtering rules:");
diff --git a/packages/Connectivity/test/Android.bp b/packages/Connectivity/test/Android.bp
deleted file mode 100644
index a6cad2e..0000000
--- a/packages/Connectivity/test/Android.bp
+++ /dev/null
@@ -1,38 +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 {
- default_applicable_licenses: ["frameworks_base_license"],
-}
-
-// defaults for tests that need to build against framework-connectivity's @hide APIs
-// Only usable from targets that have visibility on framework-connectivity.impl.
-// Instead of using this, consider avoiding to depend on hidden connectivity APIs in
-// tests.
-java_defaults {
- name: "framework-connectivity-test-defaults",
- sdk_version: "core_platform", // tests can use @CorePlatformApi's
- libs: [
- // order matters: classes in framework-connectivity are resolved before framework,
- // meaning @hide APIs in framework-connectivity are resolved before @SystemApi
- // stubs in framework
- "framework-connectivity.impl",
- "framework",
-
- // if sdk_version="" this gets automatically included, but here we need to add manually.
- "framework-res",
- ],
-}
diff --git a/packages/Connectivity/tests/common/Android.bp b/packages/Connectivity/tests/common/Android.bp
index 439665b..7331453 100644
--- a/packages/Connectivity/tests/common/Android.bp
+++ b/packages/Connectivity/tests/common/Android.bp
@@ -46,3 +46,22 @@
"android.test.base.stubs",
],
}
+
+// defaults for tests that need to build against framework-connectivity's @hide APIs
+// Only usable from targets that have visibility on framework-connectivity.impl.
+// Instead of using this, consider avoiding to depend on hidden connectivity APIs in
+// tests.
+java_defaults {
+ name: "framework-connectivity-test-defaults",
+ sdk_version: "core_platform", // tests can use @CorePlatformApi's
+ libs: [
+ // order matters: classes in framework-connectivity are resolved before framework,
+ // meaning @hide APIs in framework-connectivity are resolved before @SystemApi
+ // stubs in framework
+ "framework-connectivity.impl",
+ "framework",
+
+ // if sdk_version="" this gets automatically included, but here we need to add manually.
+ "framework-res",
+ ],
+}
diff --git a/packages/Connectivity/tests/common/java/android/net/apf/ApfCapabilitiesTest.java b/packages/Connectivity/tests/common/java/android/net/apf/ApfCapabilitiesTest.java
index d50406f..88996d9 100644
--- a/packages/Connectivity/tests/common/java/android/net/apf/ApfCapabilitiesTest.java
+++ b/packages/Connectivity/tests/common/java/android/net/apf/ApfCapabilitiesTest.java
@@ -18,6 +18,7 @@
import static com.android.testutils.ParcelUtils.assertParcelSane;
+import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
@@ -25,12 +26,17 @@
import static org.junit.Assert.assertTrue;
import android.content.Context;
+import android.os.Build;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
+
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -39,6 +45,9 @@
@RunWith(AndroidJUnit4.class)
@SmallTest
public class ApfCapabilitiesTest {
+ @Rule
+ public final DevSdkIgnoreRule mIgnoreRule = new DevSdkIgnoreRule();
+
private Context mContext;
@Before
@@ -85,6 +94,17 @@
assertEquals(shouldDrop8023Frames, actual);
}
+ @Test @IgnoreUpTo(Build.VERSION_CODES.R)
+ public void testGetApfDrop8023Frames_S() {
+ // IpClient does not call getApfDrop8023Frames() since S, so any customization of the return
+ // value on S+ is a configuration error as it will not be used by IpClient.
+ assertTrue("android.R.bool.config_apfDrop802_3Frames has been modified to false, but "
+ + "starting from S its value is not used by IpClient. If the modification is "
+ + "intentional, use a runtime resource overlay for the NetworkStack package to "
+ + "overlay com.android.networkstack.R.bool.config_apfDrop802_3Frames instead.",
+ ApfCapabilities.getApfDrop8023Frames());
+ }
+
@Test
public void testGetApfEtherTypeBlackList() {
// Get com.android.internal.R.array.config_apfEthTypeBlackList. The test cannot directly
@@ -96,4 +116,17 @@
assertNotNull(actual);
assertTrue(Arrays.equals(blacklistedEtherTypeArray, actual));
}
+
+ @Test @IgnoreUpTo(Build.VERSION_CODES.R)
+ public void testGetApfEtherTypeBlackList_S() {
+ // IpClient does not call getApfEtherTypeBlackList() since S, so any customization of the
+ // return value on S+ is a configuration error as it will not be used by IpClient.
+ assertArrayEquals("android.R.array.config_apfEthTypeBlackList has been modified, but "
+ + "starting from S its value is not used by IpClient. If the modification "
+ + "is intentional, use a runtime resource overlay for the NetworkStack "
+ + "package to overlay "
+ + "com.android.networkstack.R.array.config_apfEthTypeDenyList instead.",
+ new int[] { 0x88a2, 0x88a4, 0x88b8, 0x88cd, 0x88e3 },
+ ApfCapabilities.getApfEtherTypeBlackList());
+ }
}
diff --git a/packages/Connectivity/tests/unit/java/android/net/NetworkTemplateTest.kt b/packages/Connectivity/tests/unit/java/android/net/NetworkTemplateTest.kt
index ab6b2f4..cb39a0c 100644
--- a/packages/Connectivity/tests/unit/java/android/net/NetworkTemplateTest.kt
+++ b/packages/Connectivity/tests/unit/java/android/net/NetworkTemplateTest.kt
@@ -40,7 +40,7 @@
import android.net.NetworkTemplate.SUBSCRIBER_ID_MATCH_RULE_EXACT
import android.net.NetworkTemplate.buildTemplateWifi
import android.net.NetworkTemplate.buildTemplateWifiWildcard
-import android.net.NetworkTemplate.buildTemplateCarrier
+import android.net.NetworkTemplate.buildTemplateCarrierMetered
import android.net.NetworkTemplate.buildTemplateMobileWithRatType
import android.telephony.TelephonyManager
import com.android.testutils.assertParcelSane
@@ -73,11 +73,12 @@
type: Int,
subscriberId: String? = null,
ssid: String? = null,
- oemManaged: Int = OEM_NONE
+ oemManaged: Int = OEM_NONE,
+ metered: Boolean = true
): NetworkStateSnapshot {
val lp = LinkProperties()
val caps = NetworkCapabilities().apply {
- setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED, false)
+ setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED, !metered)
setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING, true)
setSSID(ssid)
setCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PAID,
@@ -167,25 +168,38 @@
}
@Test
- fun testCarrierMatches() {
- val templateCarrierImsi1 = buildTemplateCarrier(TEST_IMSI1)
+ fun testCarrierMeteredMatches() {
+ val templateCarrierImsi1Metered = buildTemplateCarrierMetered(TEST_IMSI1)
- val identMobile1 = buildNetworkIdentity(mockContext, buildMobileNetworkState(TEST_IMSI1),
- false, TelephonyManager.NETWORK_TYPE_UMTS)
- val identMobile2 = buildNetworkIdentity(mockContext, buildMobileNetworkState(TEST_IMSI2),
- false, TelephonyManager.NETWORK_TYPE_UMTS)
- val identWifiSsid1 = buildNetworkIdentity(
- mockContext, buildWifiNetworkState(null, TEST_SSID1), true, 0)
- val identCarrierWifiImsi1 = buildNetworkIdentity(
- mockContext, buildWifiNetworkState(TEST_IMSI1, TEST_SSID1), true, 0)
- val identCarrierWifiImsi2 = buildNetworkIdentity(
- mockContext, buildWifiNetworkState(TEST_IMSI2, TEST_SSID1), true, 0)
+ val mobileImsi1 = buildMobileNetworkState(TEST_IMSI1)
+ val mobileImsi1Unmetered = buildNetworkState(TYPE_MOBILE, TEST_IMSI1, null /* ssid */,
+ OEM_NONE, false /* metered */)
+ val mobileImsi2 = buildMobileNetworkState(TEST_IMSI2)
+ val wifiSsid1 = buildWifiNetworkState(null /* subscriberId */, TEST_SSID1)
+ val wifiImsi1Ssid1 = buildWifiNetworkState(TEST_IMSI1, TEST_SSID1)
+ val wifiImsi1Ssid1Unmetered = buildNetworkState(TYPE_WIFI, TEST_IMSI1, TEST_SSID1,
+ OEM_NONE, false /* metered */)
- templateCarrierImsi1.assertMatches(identCarrierWifiImsi1)
- templateCarrierImsi1.assertDoesNotMatch(identCarrierWifiImsi2)
- templateCarrierImsi1.assertDoesNotMatch(identWifiSsid1)
- templateCarrierImsi1.assertMatches(identMobile1)
- templateCarrierImsi1.assertDoesNotMatch(identMobile2)
+ val identMobileImsi1Metered = buildNetworkIdentity(mockContext,
+ mobileImsi1, false /* defaultNetwork */, TelephonyManager.NETWORK_TYPE_UMTS)
+ val identMobileImsi1Unmetered = buildNetworkIdentity(mockContext,
+ mobileImsi1Unmetered, false /* defaultNetwork */,
+ TelephonyManager.NETWORK_TYPE_UMTS)
+ val identMobileImsi2Metered = buildNetworkIdentity(mockContext,
+ mobileImsi2, false /* defaultNetwork */, TelephonyManager.NETWORK_TYPE_UMTS)
+ val identWifiSsid1Metered = buildNetworkIdentity(
+ mockContext, wifiSsid1, true /* defaultNetwork */, 0 /* subType */)
+ val identCarrierWifiImsi1Metered = buildNetworkIdentity(
+ mockContext, wifiImsi1Ssid1, true /* defaultNetwork */, 0 /* subType */)
+ val identCarrierWifiImsi1NonMetered = buildNetworkIdentity(mockContext,
+ wifiImsi1Ssid1Unmetered, true /* defaultNetwork */, 0 /* subType */)
+
+ templateCarrierImsi1Metered.assertMatches(identMobileImsi1Metered)
+ templateCarrierImsi1Metered.assertDoesNotMatch(identMobileImsi1Unmetered)
+ templateCarrierImsi1Metered.assertDoesNotMatch(identMobileImsi2Metered)
+ templateCarrierImsi1Metered.assertDoesNotMatch(identWifiSsid1Metered)
+ templateCarrierImsi1Metered.assertMatches(identCarrierWifiImsi1Metered)
+ templateCarrierImsi1Metered.assertDoesNotMatch(identCarrierWifiImsi1NonMetered)
}
@Test
diff --git a/packages/Connectivity/tests/unit/java/android/net/QosSocketFilterTest.java b/packages/Connectivity/tests/unit/java/android/net/QosSocketFilterTest.java
index ad58960..40f8f1b 100644
--- a/packages/Connectivity/tests/unit/java/android/net/QosSocketFilterTest.java
+++ b/packages/Connectivity/tests/unit/java/android/net/QosSocketFilterTest.java
@@ -35,7 +35,7 @@
public void testPortExactMatch() {
final InetAddress addressA = InetAddresses.parseNumericAddress("1.2.3.4");
final InetAddress addressB = InetAddresses.parseNumericAddress("1.2.3.4");
- assertTrue(QosSocketFilter.matchesLocalAddress(
+ assertTrue(QosSocketFilter.matchesAddress(
new InetSocketAddress(addressA, 10), addressB, 10, 10));
}
@@ -44,7 +44,7 @@
public void testPortLessThanStart() {
final InetAddress addressA = InetAddresses.parseNumericAddress("1.2.3.4");
final InetAddress addressB = InetAddresses.parseNumericAddress("1.2.3.4");
- assertFalse(QosSocketFilter.matchesLocalAddress(
+ assertFalse(QosSocketFilter.matchesAddress(
new InetSocketAddress(addressA, 8), addressB, 10, 10));
}
@@ -52,7 +52,7 @@
public void testPortGreaterThanEnd() {
final InetAddress addressA = InetAddresses.parseNumericAddress("1.2.3.4");
final InetAddress addressB = InetAddresses.parseNumericAddress("1.2.3.4");
- assertFalse(QosSocketFilter.matchesLocalAddress(
+ assertFalse(QosSocketFilter.matchesAddress(
new InetSocketAddress(addressA, 18), addressB, 10, 10));
}
@@ -60,7 +60,7 @@
public void testPortBetweenStartAndEnd() {
final InetAddress addressA = InetAddresses.parseNumericAddress("1.2.3.4");
final InetAddress addressB = InetAddresses.parseNumericAddress("1.2.3.4");
- assertTrue(QosSocketFilter.matchesLocalAddress(
+ assertTrue(QosSocketFilter.matchesAddress(
new InetSocketAddress(addressA, 10), addressB, 8, 18));
}
@@ -68,7 +68,7 @@
public void testAddressesDontMatch() {
final InetAddress addressA = InetAddresses.parseNumericAddress("1.2.3.4");
final InetAddress addressB = InetAddresses.parseNumericAddress("1.2.3.5");
- assertFalse(QosSocketFilter.matchesLocalAddress(
+ assertFalse(QosSocketFilter.matchesAddress(
new InetSocketAddress(addressA, 10), addressB, 10, 10));
}
}
diff --git a/packages/Connectivity/tests/unit/java/com/android/server/ConnectivityServiceTest.java b/packages/Connectivity/tests/unit/java/com/android/server/ConnectivityServiceTest.java
index 63501d7..29a411e 100644
--- a/packages/Connectivity/tests/unit/java/com/android/server/ConnectivityServiceTest.java
+++ b/packages/Connectivity/tests/unit/java/com/android/server/ConnectivityServiceTest.java
@@ -128,6 +128,7 @@
import static com.android.testutils.MiscAsserts.assertEmpty;
import static com.android.testutils.MiscAsserts.assertLength;
import static com.android.testutils.MiscAsserts.assertRunsInAtMost;
+import static com.android.testutils.MiscAsserts.assertSameElements;
import static com.android.testutils.MiscAsserts.assertThrows;
import static org.junit.Assert.assertEquals;
@@ -4276,6 +4277,124 @@
mCm.unregisterNetworkCallback(callback);
}
+ @Test
+ public void testNetworkCallbackWithNullUids() throws Exception {
+ final NetworkRequest request = new NetworkRequest.Builder()
+ .removeCapability(NET_CAPABILITY_NOT_VPN)
+ .build();
+ final TestNetworkCallback callback = new TestNetworkCallback();
+ mCm.registerNetworkCallback(request, callback);
+
+ // Attempt to file a callback for networks applying to another UID. This does not actually
+ // work, because this code does not currently have permission to do so. The callback behaves
+ // exactly the same as the one registered just above.
+ final int otherUid = UserHandle.getUid(RESTRICTED_USER, VPN_UID);
+ final NetworkRequest otherUidRequest = new NetworkRequest.Builder()
+ .removeCapability(NET_CAPABILITY_NOT_VPN)
+ .setUids(UidRange.toIntRanges(uidRangesForUids(otherUid)))
+ .build();
+ final TestNetworkCallback otherUidCallback = new TestNetworkCallback();
+ mCm.registerNetworkCallback(otherUidRequest, otherUidCallback);
+
+ final NetworkRequest includeOtherUidsRequest = new NetworkRequest.Builder()
+ .removeCapability(NET_CAPABILITY_NOT_VPN)
+ .setIncludeOtherUidNetworks(true)
+ .build();
+ final TestNetworkCallback includeOtherUidsCallback = new TestNetworkCallback();
+ mCm.registerNetworkCallback(includeOtherUidsRequest, includeOtherUidsCallback);
+
+ // Both callbacks see a network with no specifier that applies to their UID.
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+ mWiFiNetworkAgent.connect(false /* validated */);
+ callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+ otherUidCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+ includeOtherUidsCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+ mWiFiNetworkAgent.disconnect();
+ callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
+ otherUidCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
+ includeOtherUidsCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
+
+ // Only the includeOtherUidsCallback sees a VPN that does not apply to its UID.
+ final UidRange range = UidRange.createForUser(UserHandle.of(RESTRICTED_USER));
+ final Set<UidRange> vpnRanges = Collections.singleton(range);
+ mMockVpn.establish(new LinkProperties(), VPN_UID, vpnRanges);
+ includeOtherUidsCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
+ callback.assertNoCallback();
+ otherUidCallback.assertNoCallback();
+
+ mMockVpn.disconnect();
+ includeOtherUidsCallback.expectCallback(CallbackEntry.LOST, mMockVpn);
+ callback.assertNoCallback();
+ otherUidCallback.assertNoCallback();
+ }
+
+ private static class RedactableNetworkSpecifier extends NetworkSpecifier {
+ public static final int ID_INVALID = -1;
+
+ public final int networkId;
+
+ RedactableNetworkSpecifier(int networkId) {
+ this.networkId = networkId;
+ }
+
+ @Override
+ public boolean canBeSatisfiedBy(NetworkSpecifier other) {
+ return other instanceof RedactableNetworkSpecifier
+ && this.networkId == ((RedactableNetworkSpecifier) other).networkId;
+ }
+
+ @Override
+ public NetworkSpecifier redact() {
+ return new RedactableNetworkSpecifier(ID_INVALID);
+ }
+ }
+
+ @Test
+ public void testNetworkCallbackWithNullUidsRedactsSpecifier() throws Exception {
+ final RedactableNetworkSpecifier specifier = new RedactableNetworkSpecifier(42);
+ final NetworkRequest request = new NetworkRequest.Builder()
+ .addCapability(NET_CAPABILITY_INTERNET)
+ .addTransportType(TRANSPORT_WIFI)
+ .setNetworkSpecifier(specifier)
+ .build();
+ final TestNetworkCallback callback = new TestNetworkCallback();
+ mCm.registerNetworkCallback(request, callback);
+
+ // Attempt to file a callback for networks applying to another UID. This does not actually
+ // work, because this code does not currently have permission to do so. The callback behaves
+ // exactly the same as the one registered just above.
+ final int otherUid = UserHandle.getUid(RESTRICTED_USER, VPN_UID);
+ final NetworkRequest otherUidRequest = new NetworkRequest.Builder()
+ .addCapability(NET_CAPABILITY_INTERNET)
+ .addTransportType(TRANSPORT_WIFI)
+ .setNetworkSpecifier(specifier)
+ .setUids(UidRange.toIntRanges(uidRangesForUids(otherUid)))
+ .build();
+ final TestNetworkCallback otherUidCallback = new TestNetworkCallback();
+ mCm.registerNetworkCallback(otherUidRequest, otherUidCallback);
+
+ final NetworkRequest includeOtherUidsRequest = new NetworkRequest.Builder()
+ .addCapability(NET_CAPABILITY_INTERNET)
+ .addTransportType(TRANSPORT_WIFI)
+ .setNetworkSpecifier(specifier)
+ .setIncludeOtherUidNetworks(true)
+ .build();
+ final TestNetworkCallback includeOtherUidsCallback = new TestNetworkCallback();
+ mCm.registerNetworkCallback(includeOtherUidsRequest, callback);
+
+ // Only the regular callback sees the network, because callbacks filed with no UID have
+ // their specifiers redacted.
+ final LinkProperties emptyLp = new LinkProperties();
+ final NetworkCapabilities ncTemplate = new NetworkCapabilities()
+ .addTransportType(TRANSPORT_WIFI)
+ .setNetworkSpecifier(specifier);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, emptyLp, ncTemplate);
+ mWiFiNetworkAgent.connect(false /* validated */);
+ callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+ otherUidCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+ includeOtherUidsCallback.assertNoCallback();
+ }
+
private void setCaptivePortalMode(int mode) {
ContentResolver cr = mServiceContext.getContentResolver();
Settings.Global.putInt(cr, ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE, mode);
@@ -5885,20 +6004,8 @@
mCm.unregisterNetworkCallback(networkCallback);
}
- private <T> void assertSameElementsNoDuplicates(T[] expected, T[] actual) {
- // Easier to implement than a proper "assertSameElements" method that also correctly deals
- // with duplicates.
- final String msg = Arrays.toString(expected) + " != " + Arrays.toString(actual);
- assertEquals(msg, expected.length, actual.length);
- Set expectedSet = new ArraySet<>(Arrays.asList(expected));
- assertEquals("expected contains duplicates", expectedSet.size(), expected.length);
- // actual cannot have duplicates because it's the same length and has the same elements.
- Set actualSet = new ArraySet<>(Arrays.asList(actual));
- assertEquals(expectedSet, actualSet);
- }
-
- private void expectNetworkStatus(Network[] networks, String defaultIface,
- Integer vpnUid, String vpnIfname, String[] underlyingIfaces) throws Exception {
+ private void expectNotifyNetworkStatus(List<Network> networks, String defaultIface,
+ Integer vpnUid, String vpnIfname, List<String> underlyingIfaces) throws Exception {
ArgumentCaptor<List<Network>> networksCaptor = ArgumentCaptor.forClass(List.class);
ArgumentCaptor<List<UnderlyingNetworkInfo>> vpnInfosCaptor =
ArgumentCaptor.forClass(List.class);
@@ -5906,26 +6013,24 @@
verify(mStatsManager, atLeastOnce()).notifyNetworkStatus(networksCaptor.capture(),
any(List.class), eq(defaultIface), vpnInfosCaptor.capture());
- assertSameElementsNoDuplicates(networksCaptor.getValue().toArray(), networks);
+ assertSameElements(networksCaptor.getValue(), networks);
- UnderlyingNetworkInfo[] infos =
- vpnInfosCaptor.getValue().toArray(new UnderlyingNetworkInfo[0]);
+ List<UnderlyingNetworkInfo> infos = vpnInfosCaptor.getValue();
if (vpnUid != null) {
- assertEquals("Should have exactly one VPN:", 1, infos.length);
- UnderlyingNetworkInfo info = infos[0];
+ assertEquals("Should have exactly one VPN:", 1, infos.size());
+ UnderlyingNetworkInfo info = infos.get(0);
assertEquals("Unexpected VPN owner:", (int) vpnUid, info.getOwnerUid());
assertEquals("Unexpected VPN interface:", vpnIfname, info.getInterface());
- assertSameElementsNoDuplicates(underlyingIfaces,
- info.getUnderlyingInterfaces().toArray(new String[0]));
+ assertSameElements(underlyingIfaces, info.getUnderlyingInterfaces());
} else {
- assertEquals(0, infos.length);
+ assertEquals(0, infos.size());
return;
}
}
- private void expectNetworkStatus(
- Network[] networks, String defaultIface) throws Exception {
- expectNetworkStatus(networks, defaultIface, null, null, new String[0]);
+ private void expectNotifyNetworkStatus(
+ List<Network> networks, String defaultIface) throws Exception {
+ expectNotifyNetworkStatus(networks, defaultIface, null, null, List.of());
}
@Test
@@ -5933,8 +6038,8 @@
mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
- final Network[] onlyCell = new Network[] {mCellNetworkAgent.getNetwork()};
- final Network[] onlyWifi = new Network[] {mWiFiNetworkAgent.getNetwork()};
+ final List<Network> onlyCell = List.of(mCellNetworkAgent.getNetwork());
+ final List<Network> onlyWifi = List.of(mWiFiNetworkAgent.getNetwork());
LinkProperties cellLp = new LinkProperties();
cellLp.setInterfaceName(MOBILE_IFNAME);
@@ -5945,7 +6050,7 @@
mCellNetworkAgent.connect(false);
mCellNetworkAgent.sendLinkProperties(cellLp);
waitForIdle();
- expectNetworkStatus(onlyCell, MOBILE_IFNAME);
+ expectNotifyNetworkStatus(onlyCell, MOBILE_IFNAME);
reset(mStatsManager);
// Default network switch should update ifaces.
@@ -5953,37 +6058,37 @@
mWiFiNetworkAgent.sendLinkProperties(wifiLp);
waitForIdle();
assertEquals(wifiLp, mService.getActiveLinkProperties());
- expectNetworkStatus(onlyWifi, WIFI_IFNAME);
+ expectNotifyNetworkStatus(onlyWifi, WIFI_IFNAME);
reset(mStatsManager);
// Disconnect should update ifaces.
mWiFiNetworkAgent.disconnect();
waitForIdle();
- expectNetworkStatus(onlyCell, MOBILE_IFNAME);
+ expectNotifyNetworkStatus(onlyCell, MOBILE_IFNAME);
reset(mStatsManager);
// Metered change should update ifaces
mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
waitForIdle();
- expectNetworkStatus(onlyCell, MOBILE_IFNAME);
+ expectNotifyNetworkStatus(onlyCell, MOBILE_IFNAME);
reset(mStatsManager);
mCellNetworkAgent.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
waitForIdle();
- expectNetworkStatus(onlyCell, MOBILE_IFNAME);
+ expectNotifyNetworkStatus(onlyCell, MOBILE_IFNAME);
reset(mStatsManager);
// Temp metered change shouldn't update ifaces
mCellNetworkAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
waitForIdle();
- verify(mStatsManager, never()).notifyNetworkStatus(eq(Arrays.asList(onlyCell)),
+ verify(mStatsManager, never()).notifyNetworkStatus(eq(onlyCell),
any(List.class), eq(MOBILE_IFNAME), any(List.class));
reset(mStatsManager);
// Roaming change should update ifaces
mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
waitForIdle();
- expectNetworkStatus(onlyCell, MOBILE_IFNAME);
+ expectNotifyNetworkStatus(onlyCell, MOBILE_IFNAME);
reset(mStatsManager);
// Test VPNs.
@@ -5993,29 +6098,29 @@
mMockVpn.establishForMyUid(lp);
assertUidRangesUpdatedForMyUid(true);
- final Network[] cellAndVpn = new Network[] {
- mCellNetworkAgent.getNetwork(), mMockVpn.getNetwork()};
+ final List<Network> cellAndVpn =
+ List.of(mCellNetworkAgent.getNetwork(), mMockVpn.getNetwork());
// A VPN with default (null) underlying networks sets the underlying network's interfaces...
- expectNetworkStatus(cellAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME,
- new String[]{MOBILE_IFNAME});
+ expectNotifyNetworkStatus(cellAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME,
+ List.of(MOBILE_IFNAME));
// ...and updates them as the default network switches.
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(false);
mWiFiNetworkAgent.sendLinkProperties(wifiLp);
final Network[] onlyNull = new Network[]{null};
- final Network[] wifiAndVpn = new Network[] {
- mWiFiNetworkAgent.getNetwork(), mMockVpn.getNetwork()};
- final Network[] cellAndWifi = new Network[] {
- mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork()};
- final Network[] cellNullAndWifi = new Network[] {
- mCellNetworkAgent.getNetwork(), null, mWiFiNetworkAgent.getNetwork()};
+ final List<Network> wifiAndVpn =
+ List.of(mWiFiNetworkAgent.getNetwork(), mMockVpn.getNetwork());
+ final List<Network> cellAndWifi =
+ List.of(mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork());
+ final Network[] cellNullAndWifi =
+ new Network[]{mCellNetworkAgent.getNetwork(), null, mWiFiNetworkAgent.getNetwork()};
waitForIdle();
assertEquals(wifiLp, mService.getActiveLinkProperties());
- expectNetworkStatus(wifiAndVpn, WIFI_IFNAME, Process.myUid(), VPN_IFNAME,
- new String[]{WIFI_IFNAME});
+ expectNotifyNetworkStatus(wifiAndVpn, WIFI_IFNAME, Process.myUid(), VPN_IFNAME,
+ List.of(WIFI_IFNAME));
reset(mStatsManager);
// A VPN that sets its underlying networks passes the underlying interfaces, and influences
@@ -6024,23 +6129,23 @@
// MOBILE_IFNAME even though the default network is wifi.
// TODO: fix this to pass in the actual default network interface. Whether or not the VPN
// applies to the system server UID should not have any bearing on network stats.
- mMockVpn.setUnderlyingNetworks(onlyCell);
+ mMockVpn.setUnderlyingNetworks(onlyCell.toArray(new Network[0]));
waitForIdle();
- expectNetworkStatus(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME,
- new String[]{MOBILE_IFNAME});
+ expectNotifyNetworkStatus(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME,
+ List.of(MOBILE_IFNAME));
reset(mStatsManager);
- mMockVpn.setUnderlyingNetworks(cellAndWifi);
+ mMockVpn.setUnderlyingNetworks(cellAndWifi.toArray(new Network[0]));
waitForIdle();
- expectNetworkStatus(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME,
- new String[]{MOBILE_IFNAME, WIFI_IFNAME});
+ expectNotifyNetworkStatus(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME,
+ List.of(MOBILE_IFNAME, WIFI_IFNAME));
reset(mStatsManager);
// Null underlying networks are ignored.
mMockVpn.setUnderlyingNetworks(cellNullAndWifi);
waitForIdle();
- expectNetworkStatus(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME,
- new String[]{MOBILE_IFNAME, WIFI_IFNAME});
+ expectNotifyNetworkStatus(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME,
+ List.of(MOBILE_IFNAME, WIFI_IFNAME));
reset(mStatsManager);
// If an underlying network disconnects, that interface should no longer be underlying.
@@ -6053,8 +6158,8 @@
mCellNetworkAgent.disconnect();
waitForIdle();
assertNull(mService.getLinkProperties(mCellNetworkAgent.getNetwork()));
- expectNetworkStatus(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME,
- new String[]{MOBILE_IFNAME, WIFI_IFNAME});
+ expectNotifyNetworkStatus(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME,
+ List.of(MOBILE_IFNAME, WIFI_IFNAME));
// Confirm that we never tell NetworkStatsService that cell is no longer the underlying
// network for the VPN...
@@ -6089,26 +6194,26 @@
// Also, for the same reason as above, the active interface passed in is null.
mMockVpn.setUnderlyingNetworks(new Network[0]);
waitForIdle();
- expectNetworkStatus(wifiAndVpn, null);
+ expectNotifyNetworkStatus(wifiAndVpn, null);
reset(mStatsManager);
// Specifying only a null underlying network is the same as no networks.
mMockVpn.setUnderlyingNetworks(onlyNull);
waitForIdle();
- expectNetworkStatus(wifiAndVpn, null);
+ expectNotifyNetworkStatus(wifiAndVpn, null);
reset(mStatsManager);
// Specifying networks that are all disconnected is the same as specifying no networks.
- mMockVpn.setUnderlyingNetworks(onlyCell);
+ mMockVpn.setUnderlyingNetworks(onlyCell.toArray(new Network[0]));
waitForIdle();
- expectNetworkStatus(wifiAndVpn, null);
+ expectNotifyNetworkStatus(wifiAndVpn, null);
reset(mStatsManager);
// Passing in null again means follow the default network again.
mMockVpn.setUnderlyingNetworks(null);
waitForIdle();
- expectNetworkStatus(wifiAndVpn, WIFI_IFNAME, Process.myUid(), VPN_IFNAME,
- new String[]{WIFI_IFNAME});
+ expectNotifyNetworkStatus(wifiAndVpn, WIFI_IFNAME, Process.myUid(), VPN_IFNAME,
+ List.of(WIFI_IFNAME));
reset(mStatsManager);
}
diff --git a/packages/Connectivity/tests/unit/java/com/android/server/connectivity/NetworkRankerTest.kt b/packages/Connectivity/tests/unit/java/com/android/server/connectivity/NetworkRankerTest.kt
index 551b94c..4408958 100644
--- a/packages/Connectivity/tests/unit/java/com/android/server/connectivity/NetworkRankerTest.kt
+++ b/packages/Connectivity/tests/unit/java/com/android/server/connectivity/NetworkRankerTest.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,74 +17,156 @@
package com.android.server.connectivity
import android.net.NetworkCapabilities
-import android.net.NetworkRequest
+import android.net.NetworkCapabilities.TRANSPORT_CELLULAR
+import android.net.NetworkCapabilities.TRANSPORT_WIFI
import android.net.NetworkScore.KEEP_CONNECTED_NONE
+import android.net.NetworkScore.POLICY_EXITING
+import android.net.NetworkScore.POLICY_TRANSPORT_PRIMARY
+import android.net.NetworkScore.POLICY_YIELD_TO_BAD_WIFI
+import android.os.Build
import androidx.test.filters.SmallTest
-import androidx.test.runner.AndroidJUnit4
+import com.android.server.connectivity.FullScore.POLICY_EVER_VALIDATED_NOT_AVOIDED_WHEN_BAD
+import com.android.server.connectivity.FullScore.POLICY_IS_VALIDATED
+import com.android.testutils.DevSdkIgnoreRule
+import com.android.testutils.DevSdkIgnoreRunner
import org.junit.Test
import org.junit.runner.RunWith
-import org.mockito.ArgumentMatchers.any
-import org.mockito.Mockito.doReturn
-import org.mockito.Mockito.mock
import kotlin.test.assertEquals
-import kotlin.test.assertNull
-@RunWith(AndroidJUnit4::class)
+private fun score(vararg policies: Int) = FullScore(0,
+ policies.fold(0L) { acc, e -> acc or (1L shl e) }, KEEP_CONNECTED_NONE)
+private fun caps(transport: Int) = NetworkCapabilities.Builder().addTransportType(transport).build()
+
@SmallTest
+@RunWith(DevSdkIgnoreRunner::class)
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
class NetworkRankerTest {
- private val ranker = NetworkRanker()
+ private val mRanker = NetworkRanker()
- private fun makeNai(satisfy: Boolean, legacyScore: Int) =
- mock(NetworkAgentInfo::class.java).also {
- doReturn(satisfy).`when`(it).satisfies(any())
- val fs = FullScore(legacyScore, 0 /* policies */, KEEP_CONNECTED_NONE)
- doReturn(fs).`when`(it).getScore()
- val nc = NetworkCapabilities.Builder().build()
- doReturn(nc).`when`(it).getCapsNoCopy()
- }
-
- @Test
- fun testGetBestNetwork() {
- val scores = listOf(20, 50, 90, 60, 23, 68)
- val nais = scores.map { makeNai(true, it) }
- val bestNetwork = nais[2] // The one with the top score
- val someRequest = mock(NetworkRequest::class.java)
- assertEquals(bestNetwork, ranker.getBestNetwork(someRequest, nais, bestNetwork))
+ private class TestScore(private val sc: FullScore, private val nc: NetworkCapabilities)
+ : NetworkRanker.Scoreable {
+ override fun getScore() = sc
+ override fun getCapsNoCopy(): NetworkCapabilities = nc
}
@Test
- fun testIgnoreNonSatisfying() {
- val nais = listOf(makeNai(true, 20), makeNai(true, 50), makeNai(false, 90),
- makeNai(false, 60), makeNai(true, 23), makeNai(false, 68))
- val bestNetwork = nais[1] // Top score that's satisfying
- val someRequest = mock(NetworkRequest::class.java)
- assertEquals(bestNetwork, ranker.getBestNetwork(someRequest, nais, nais[1]))
+ fun testYieldToBadWiFiOneCell() {
+ // Only cell, it wins
+ val winner = TestScore(score(POLICY_YIELD_TO_BAD_WIFI, POLICY_IS_VALIDATED),
+ caps(TRANSPORT_CELLULAR))
+ val scores = listOf(winner)
+ assertEquals(winner, mRanker.getBestNetworkByPolicy(scores, null))
}
@Test
- fun testNoMatch() {
- val nais = listOf(makeNai(false, 20), makeNai(false, 50), makeNai(false, 90))
- val someRequest = mock(NetworkRequest::class.java)
- assertNull(ranker.getBestNetwork(someRequest, nais, null))
+ fun testYieldToBadWiFiOneCellOneBadWiFi() {
+ // Bad wifi wins against yielding validated cell
+ val winner = TestScore(score(POLICY_EVER_VALIDATED_NOT_AVOIDED_WHEN_BAD),
+ caps(TRANSPORT_WIFI))
+ val scores = listOf(
+ winner,
+ TestScore(score(POLICY_YIELD_TO_BAD_WIFI, POLICY_IS_VALIDATED),
+ caps(TRANSPORT_CELLULAR))
+ )
+ assertEquals(winner, mRanker.getBestNetworkByPolicy(scores, null))
}
@Test
- fun testEmpty() {
- val someRequest = mock(NetworkRequest::class.java)
- assertNull(ranker.getBestNetwork(someRequest, emptyList(), null))
+ fun testYieldToBadWiFiOneCellTwoBadWiFi() {
+ // Bad wifi wins against yielding validated cell. Prefer the one that's primary.
+ val winner = TestScore(score(POLICY_EVER_VALIDATED_NOT_AVOIDED_WHEN_BAD,
+ POLICY_TRANSPORT_PRIMARY), caps(TRANSPORT_WIFI))
+ val scores = listOf(
+ winner,
+ TestScore(score(POLICY_EVER_VALIDATED_NOT_AVOIDED_WHEN_BAD),
+ caps(TRANSPORT_WIFI)),
+ TestScore(score(POLICY_YIELD_TO_BAD_WIFI, POLICY_IS_VALIDATED),
+ caps(TRANSPORT_CELLULAR))
+ )
+ assertEquals(winner, mRanker.getBestNetworkByPolicy(scores, null))
}
- // Make sure the ranker is "stable" (as in stable sort), that is, it always returns the FIRST
- // network satisfying the request if multiple of them have the same score.
@Test
- fun testStable() {
- val nais1 = listOf(makeNai(true, 30), makeNai(true, 30), makeNai(true, 30),
- makeNai(true, 30), makeNai(true, 30), makeNai(true, 30))
- val someRequest = mock(NetworkRequest::class.java)
- assertEquals(nais1[0], ranker.getBestNetwork(someRequest, nais1, nais1[0]))
+ fun testYieldToBadWiFiOneCellTwoBadWiFiOneNotAvoided() {
+ // Bad wifi ever validated wins against bad wifi that never was validated (or was
+ // avoided when bad).
+ val winner = TestScore(score(POLICY_EVER_VALIDATED_NOT_AVOIDED_WHEN_BAD),
+ caps(TRANSPORT_WIFI))
+ val scores = listOf(
+ winner,
+ TestScore(score(), caps(TRANSPORT_WIFI)),
+ TestScore(score(POLICY_YIELD_TO_BAD_WIFI, POLICY_IS_VALIDATED),
+ caps(TRANSPORT_CELLULAR))
+ )
+ assertEquals(winner, mRanker.getBestNetworkByPolicy(scores, null))
+ }
- val nais2 = listOf(makeNai(true, 30), makeNai(true, 50), makeNai(true, 20),
- makeNai(true, 50), makeNai(true, 50), makeNai(true, 40))
- assertEquals(nais2[1], ranker.getBestNetwork(someRequest, nais2, nais2[1]))
+ @Test
+ fun testYieldToBadWiFiOneCellOneBadWiFiOneGoodWiFi() {
+ // Good wifi wins
+ val winner = TestScore(score(POLICY_EVER_VALIDATED_NOT_AVOIDED_WHEN_BAD,
+ POLICY_IS_VALIDATED), caps(TRANSPORT_WIFI))
+ val scores = listOf(
+ winner,
+ TestScore(score(POLICY_EVER_VALIDATED_NOT_AVOIDED_WHEN_BAD,
+ POLICY_TRANSPORT_PRIMARY), caps(TRANSPORT_WIFI)),
+ TestScore(score(POLICY_YIELD_TO_BAD_WIFI, POLICY_IS_VALIDATED),
+ caps(TRANSPORT_CELLULAR))
+ )
+ assertEquals(winner, mRanker.getBestNetworkByPolicy(scores, null))
+ }
+
+ @Test
+ fun testYieldToBadWiFiTwoCellsOneBadWiFi() {
+ // Cell that doesn't yield wins over cell that yields and bad wifi
+ val winner = TestScore(score(POLICY_IS_VALIDATED), caps(TRANSPORT_CELLULAR))
+ val scores = listOf(
+ winner,
+ TestScore(score(POLICY_EVER_VALIDATED_NOT_AVOIDED_WHEN_BAD,
+ POLICY_TRANSPORT_PRIMARY), caps(TRANSPORT_WIFI)),
+ TestScore(score(POLICY_YIELD_TO_BAD_WIFI, POLICY_IS_VALIDATED),
+ caps(TRANSPORT_CELLULAR))
+ )
+ assertEquals(winner, mRanker.getBestNetworkByPolicy(scores, null))
+ }
+
+ @Test
+ fun testYieldToBadWiFiTwoCellsOneBadWiFiOneGoodWiFi() {
+ // Good wifi wins over cell that doesn't yield and cell that yields
+ val winner = TestScore(score(POLICY_IS_VALIDATED), caps(TRANSPORT_WIFI))
+ val scores = listOf(
+ winner,
+ TestScore(score(POLICY_EVER_VALIDATED_NOT_AVOIDED_WHEN_BAD,
+ POLICY_TRANSPORT_PRIMARY), caps(TRANSPORT_WIFI)),
+ TestScore(score(POLICY_IS_VALIDATED), caps(TRANSPORT_CELLULAR)),
+ TestScore(score(POLICY_YIELD_TO_BAD_WIFI, POLICY_IS_VALIDATED),
+ caps(TRANSPORT_CELLULAR))
+ )
+ assertEquals(winner, mRanker.getBestNetworkByPolicy(scores, null))
+ }
+
+ @Test
+ fun testYieldToBadWiFiOneExitingGoodWiFi() {
+ // Yielding cell wins over good exiting wifi
+ val winner = TestScore(score(POLICY_YIELD_TO_BAD_WIFI, POLICY_IS_VALIDATED),
+ caps(TRANSPORT_CELLULAR))
+ val scores = listOf(
+ winner,
+ TestScore(score(POLICY_IS_VALIDATED, POLICY_EXITING), caps(TRANSPORT_WIFI))
+ )
+ assertEquals(winner, mRanker.getBestNetworkByPolicy(scores, null))
+ }
+
+ @Test
+ fun testYieldToBadWiFiOneExitingBadWiFi() {
+ // Yielding cell wins over bad exiting wifi
+ val winner = TestScore(score(POLICY_YIELD_TO_BAD_WIFI, POLICY_IS_VALIDATED),
+ caps(TRANSPORT_CELLULAR))
+ val scores = listOf(
+ winner,
+ TestScore(score(POLICY_EVER_VALIDATED_NOT_AVOIDED_WHEN_BAD,
+ POLICY_EXITING), caps(TRANSPORT_WIFI))
+ )
+ assertEquals(winner, mRanker.getBestNetworkByPolicy(scores, null))
}
}
diff --git a/packages/Connectivity/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java b/packages/Connectivity/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java
index 02a5808..c75618f 100644
--- a/packages/Connectivity/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java
+++ b/packages/Connectivity/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java
@@ -30,6 +30,8 @@
import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_REQUIRED;
import static android.content.pm.PackageManager.GET_PERMISSIONS;
import static android.content.pm.PackageManager.MATCH_ANY_USER;
+import static android.net.ConnectivitySettingsManager.APPS_ALLOWED_ON_RESTRICTED_NETWORKS;
+import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
import static android.os.Process.SYSTEM_UID;
import static com.android.server.connectivity.PermissionMonitor.NETWORK;
@@ -43,8 +45,10 @@
import static org.junit.Assert.assertTrue;
import static org.mockito.AdditionalMatchers.aryEq;
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.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
@@ -61,6 +65,7 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
+import android.database.ContentObserver;
import android.net.INetd;
import android.net.UidRange;
import android.net.Uri;
@@ -68,6 +73,7 @@
import android.os.SystemConfigManager;
import android.os.UserHandle;
import android.os.UserManager;
+import android.util.ArraySet;
import android.util.SparseIntArray;
import androidx.test.InstrumentationRegistry;
@@ -136,6 +142,7 @@
final Context asUserCtx = mock(Context.class, AdditionalAnswers.delegatesTo(mContext));
doReturn(UserHandle.ALL).when(asUserCtx).getUser();
when(mContext.createContextAsUser(eq(UserHandle.ALL), anyInt())).thenReturn(asUserCtx);
+ when(mDeps.getAppsAllowedOnRestrictedNetworks(any())).thenReturn(new ArraySet<>());
mPermissionMonitor = spy(new PermissionMonitor(mContext, mNetdService, mDeps));
@@ -145,8 +152,15 @@
private boolean hasRestrictedNetworkPermission(String partition, int targetSdkVersion, int uid,
String... permissions) {
+ return hasRestrictedNetworkPermission(
+ partition, targetSdkVersion, "" /* packageName */, uid, permissions);
+ }
+
+ private boolean hasRestrictedNetworkPermission(String partition, int targetSdkVersion,
+ String packageName, int uid, String... permissions) {
final PackageInfo packageInfo =
packageInfoWithPermissions(REQUESTED_PERMISSION_GRANTED, permissions, partition);
+ packageInfo.packageName = packageName;
packageInfo.applicationInfo.targetSdkVersion = targetSdkVersion;
packageInfo.applicationInfo.uid = uid;
return mPermissionMonitor.hasRestrictedNetworkPermission(packageInfo);
@@ -280,6 +294,8 @@
PARTITION_SYSTEM, VERSION_P, MOCK_UID1, CONNECTIVITY_USE_RESTRICTED_NETWORKS));
assertFalse(hasRestrictedNetworkPermission(
PARTITION_SYSTEM, VERSION_P, MOCK_UID1, CHANGE_WIFI_STATE));
+ assertTrue(hasRestrictedNetworkPermission(
+ PARTITION_SYSTEM, VERSION_P, MOCK_UID1, PERMISSION_MAINLINE_NETWORK_STACK));
assertFalse(hasRestrictedNetworkPermission(PARTITION_SYSTEM, VERSION_Q, MOCK_UID1));
assertFalse(hasRestrictedNetworkPermission(
@@ -324,6 +340,90 @@
PARTITION_VENDOR, VERSION_Q, MOCK_UID1, CHANGE_NETWORK_STATE));
}
+ @Test
+ public void testHasRestrictedNetworkPermissionAppAllowedOnRestrictedNetworks() {
+ mPermissionMonitor.updateAppsAllowedOnRestrictedNetworks(
+ new ArraySet<>(new String[] { MOCK_PACKAGE1 }));
+ assertTrue(hasRestrictedNetworkPermission(
+ PARTITION_VENDOR, VERSION_Q, MOCK_PACKAGE1, MOCK_UID1));
+ assertTrue(hasRestrictedNetworkPermission(
+ PARTITION_VENDOR, VERSION_Q, MOCK_PACKAGE1, MOCK_UID1, CHANGE_NETWORK_STATE));
+ assertTrue(hasRestrictedNetworkPermission(
+ PARTITION_VENDOR, VERSION_Q, MOCK_PACKAGE1, MOCK_UID1, CONNECTIVITY_INTERNAL));
+
+ assertFalse(hasRestrictedNetworkPermission(
+ PARTITION_VENDOR, VERSION_Q, MOCK_PACKAGE2, MOCK_UID1));
+ assertFalse(hasRestrictedNetworkPermission(
+ PARTITION_VENDOR, VERSION_Q, MOCK_PACKAGE2, MOCK_UID1, CHANGE_NETWORK_STATE));
+ assertFalse(hasRestrictedNetworkPermission(
+ PARTITION_VENDOR, VERSION_Q, MOCK_PACKAGE2, MOCK_UID1, CONNECTIVITY_INTERNAL));
+
+ }
+
+ private boolean wouldBeCarryoverPackage(String partition, int targetSdkVersion, int uid) {
+ final PackageInfo packageInfo = packageInfoWithPermissions(
+ REQUESTED_PERMISSION_GRANTED, new String[] {}, partition);
+ packageInfo.applicationInfo.targetSdkVersion = targetSdkVersion;
+ packageInfo.applicationInfo.uid = uid;
+ return mPermissionMonitor.isCarryoverPackage(packageInfo.applicationInfo);
+ }
+
+ @Test
+ public void testIsCarryoverPackage() {
+ doReturn(VERSION_P).when(mDeps).getDeviceFirstSdkInt();
+ assertTrue(wouldBeCarryoverPackage(PARTITION_SYSTEM, VERSION_P, SYSTEM_UID));
+ assertTrue(wouldBeCarryoverPackage(PARTITION_VENDOR, VERSION_P, SYSTEM_UID));
+ assertFalse(wouldBeCarryoverPackage(PARTITION_SYSTEM, VERSION_P, MOCK_UID1));
+ assertTrue(wouldBeCarryoverPackage(PARTITION_VENDOR, VERSION_P, MOCK_UID1));
+ assertTrue(wouldBeCarryoverPackage(PARTITION_SYSTEM, VERSION_Q, SYSTEM_UID));
+ assertTrue(wouldBeCarryoverPackage(PARTITION_VENDOR, VERSION_Q, SYSTEM_UID));
+ assertFalse(wouldBeCarryoverPackage(PARTITION_SYSTEM, VERSION_Q, MOCK_UID1));
+ assertFalse(wouldBeCarryoverPackage(PARTITION_VENDOR, VERSION_Q, MOCK_UID1));
+
+ doReturn(VERSION_Q).when(mDeps).getDeviceFirstSdkInt();
+ assertFalse(wouldBeCarryoverPackage(PARTITION_SYSTEM, VERSION_P, SYSTEM_UID));
+ assertTrue(wouldBeCarryoverPackage(PARTITION_VENDOR, VERSION_P, SYSTEM_UID));
+ assertFalse(wouldBeCarryoverPackage(PARTITION_SYSTEM, VERSION_P, MOCK_UID1));
+ assertTrue(wouldBeCarryoverPackage(PARTITION_VENDOR, VERSION_P, MOCK_UID1));
+ assertFalse(wouldBeCarryoverPackage(PARTITION_SYSTEM, VERSION_Q, SYSTEM_UID));
+ assertFalse(wouldBeCarryoverPackage(PARTITION_VENDOR, VERSION_Q, SYSTEM_UID));
+ assertFalse(wouldBeCarryoverPackage(PARTITION_SYSTEM, VERSION_Q, MOCK_UID1));
+ assertFalse(wouldBeCarryoverPackage(PARTITION_VENDOR, VERSION_Q, MOCK_UID1));
+
+ assertFalse(wouldBeCarryoverPackage(PARTITION_OEM, VERSION_Q, SYSTEM_UID));
+ assertFalse(wouldBeCarryoverPackage(PARTITION_PRODUCT, VERSION_Q, SYSTEM_UID));
+ assertFalse(wouldBeCarryoverPackage(PARTITION_OEM, VERSION_Q, MOCK_UID1));
+ assertFalse(wouldBeCarryoverPackage(PARTITION_PRODUCT, VERSION_Q, MOCK_UID1));
+ }
+
+ private boolean wouldBeAppAllowedOnRestrictedNetworks(String packageName) {
+ final PackageInfo packageInfo = new PackageInfo();
+ packageInfo.packageName = packageName;
+ return mPermissionMonitor.isAppAllowedOnRestrictedNetworks(packageInfo);
+ }
+
+ @Test
+ public void testIsAppAllowedOnRestrictedNetworks() {
+ mPermissionMonitor.updateAppsAllowedOnRestrictedNetworks(new ArraySet<>());
+ assertFalse(wouldBeAppAllowedOnRestrictedNetworks(MOCK_PACKAGE1));
+ assertFalse(wouldBeAppAllowedOnRestrictedNetworks(MOCK_PACKAGE2));
+
+ mPermissionMonitor.updateAppsAllowedOnRestrictedNetworks(
+ new ArraySet<>(new String[] { MOCK_PACKAGE1 }));
+ assertTrue(wouldBeAppAllowedOnRestrictedNetworks(MOCK_PACKAGE1));
+ assertFalse(wouldBeAppAllowedOnRestrictedNetworks(MOCK_PACKAGE2));
+
+ mPermissionMonitor.updateAppsAllowedOnRestrictedNetworks(
+ new ArraySet<>(new String[] { MOCK_PACKAGE2 }));
+ assertFalse(wouldBeAppAllowedOnRestrictedNetworks(MOCK_PACKAGE1));
+ assertTrue(wouldBeAppAllowedOnRestrictedNetworks(MOCK_PACKAGE2));
+
+ mPermissionMonitor.updateAppsAllowedOnRestrictedNetworks(
+ new ArraySet<>(new String[] { "com.android.test" }));
+ assertFalse(wouldBeAppAllowedOnRestrictedNetworks(MOCK_PACKAGE1));
+ assertFalse(wouldBeAppAllowedOnRestrictedNetworks(MOCK_PACKAGE2));
+ }
+
private void assertBackgroundPermission(boolean hasPermission, String name, int uid,
String... permissions) throws Exception {
when(mPackageManager.getPackageInfo(eq(name), anyInt()))
@@ -800,4 +900,102 @@
mNetdServiceMonitor.expectPermission(INetd.PERMISSION_UNINSTALLED, new int[] { MOCK_UID1 });
}
-}
+ @Test
+ public void testAppsAllowedOnRestrictedNetworksChanged() throws Exception {
+ final NetdMonitor mNetdMonitor = new NetdMonitor(mNetdService);
+ final ArgumentCaptor<ContentObserver> captor =
+ ArgumentCaptor.forClass(ContentObserver.class);
+ verify(mDeps, times(1)).registerContentObserver(any(),
+ argThat(uri -> uri.getEncodedPath().contains(APPS_ALLOWED_ON_RESTRICTED_NETWORKS)),
+ anyBoolean(), captor.capture());
+ final ContentObserver contentObserver = captor.getValue();
+
+ mPermissionMonitor.onUserAdded(MOCK_USER1);
+ // Prepare PackageInfo for MOCK_PACKAGE1
+ final PackageInfo packageInfo = buildPackageInfo(
+ false /* hasSystemPermission */, MOCK_UID1, MOCK_USER1);
+ packageInfo.packageName = MOCK_PACKAGE1;
+ when(mPackageManager.getPackageInfo(eq(MOCK_PACKAGE1), anyInt())).thenReturn(packageInfo);
+ when(mPackageManager.getPackagesForUid(MOCK_UID1)).thenReturn(new String[]{MOCK_PACKAGE1});
+ // Prepare PackageInfo for MOCK_PACKAGE2
+ final PackageInfo packageInfo2 = buildPackageInfo(
+ false /* hasSystemPermission */, MOCK_UID2, MOCK_USER1);
+ packageInfo2.packageName = MOCK_PACKAGE2;
+ when(mPackageManager.getPackageInfo(eq(MOCK_PACKAGE2), anyInt())).thenReturn(packageInfo2);
+ when(mPackageManager.getPackagesForUid(MOCK_UID2)).thenReturn(new String[]{MOCK_PACKAGE2});
+
+ // MOCK_PACKAGE1 is listed in setting that allow to use restricted networks, MOCK_UID1
+ // should have SYSTEM permission.
+ when(mDeps.getAppsAllowedOnRestrictedNetworks(any())).thenReturn(
+ new ArraySet<>(new String[] { MOCK_PACKAGE1 }));
+ contentObserver.onChange(true /* selfChange */);
+ mNetdMonitor.expectPermission(SYSTEM, new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1});
+ mNetdMonitor.expectNoPermission(new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID2});
+
+ // MOCK_PACKAGE2 is listed in setting that allow to use restricted networks, MOCK_UID2
+ // should have SYSTEM permission but MOCK_UID1 should revoke permission.
+ when(mDeps.getAppsAllowedOnRestrictedNetworks(any())).thenReturn(
+ new ArraySet<>(new String[] { MOCK_PACKAGE2 }));
+ contentObserver.onChange(true /* selfChange */);
+ mNetdMonitor.expectPermission(SYSTEM, new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID2});
+ mNetdMonitor.expectNoPermission(new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1});
+
+ // No app lists in setting, should revoke permission from all uids.
+ when(mDeps.getAppsAllowedOnRestrictedNetworks(any())).thenReturn(new ArraySet<>());
+ contentObserver.onChange(true /* selfChange */);
+ mNetdMonitor.expectNoPermission(
+ new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1, MOCK_UID2});
+ }
+
+ @Test
+ public void testAppsAllowedOnRestrictedNetworksChangedWithSharedUid() throws Exception {
+ final NetdMonitor mNetdMonitor = new NetdMonitor(mNetdService);
+ final ArgumentCaptor<ContentObserver> captor =
+ ArgumentCaptor.forClass(ContentObserver.class);
+ verify(mDeps, times(1)).registerContentObserver(any(),
+ argThat(uri -> uri.getEncodedPath().contains(APPS_ALLOWED_ON_RESTRICTED_NETWORKS)),
+ anyBoolean(), captor.capture());
+ final ContentObserver contentObserver = captor.getValue();
+
+ mPermissionMonitor.onUserAdded(MOCK_USER1);
+ // Prepare PackageInfo for MOCK_PACKAGE1 and MOCK_PACKAGE2 with shared uid MOCK_UID1.
+ final PackageInfo packageInfo = systemPackageInfoWithPermissions(CHANGE_NETWORK_STATE);
+ packageInfo.applicationInfo.uid = MOCK_USER1.getUid(MOCK_UID1);
+ packageInfo.packageName = MOCK_PACKAGE1;
+ final PackageInfo packageInfo2 = buildPackageInfo(
+ false /* hasSystemPermission */, MOCK_UID1, MOCK_USER1);
+ packageInfo2.packageName = MOCK_PACKAGE2;
+ when(mPackageManager.getPackageInfo(eq(MOCK_PACKAGE1), anyInt())).thenReturn(packageInfo);
+ when(mPackageManager.getPackageInfo(eq(MOCK_PACKAGE2), anyInt())).thenReturn(packageInfo2);
+ when(mPackageManager.getPackagesForUid(MOCK_UID1))
+ .thenReturn(new String[]{MOCK_PACKAGE1, MOCK_PACKAGE2});
+
+ // MOCK_PACKAGE1 have CHANGE_NETWORK_STATE, MOCK_UID1 should have NETWORK permission.
+ addPackageForUsers(new UserHandle[]{MOCK_USER1}, MOCK_PACKAGE1, MOCK_UID1);
+ mNetdMonitor.expectPermission(NETWORK, new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1});
+
+ // MOCK_PACKAGE2 is listed in setting that allow to use restricted networks, MOCK_UID1
+ // should upgrade to SYSTEM permission.
+ when(mDeps.getAppsAllowedOnRestrictedNetworks(any())).thenReturn(
+ new ArraySet<>(new String[] { MOCK_PACKAGE2 }));
+ contentObserver.onChange(true /* selfChange */);
+ mNetdMonitor.expectPermission(SYSTEM, new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1});
+
+ // MOCK_PACKAGE1 is listed in setting that allow to use restricted networks, MOCK_UID1
+ // should still have SYSTEM permission.
+ when(mDeps.getAppsAllowedOnRestrictedNetworks(any())).thenReturn(
+ new ArraySet<>(new String[] { MOCK_PACKAGE1 }));
+ contentObserver.onChange(true /* selfChange */);
+ mNetdMonitor.expectPermission(SYSTEM, new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1});
+
+ // No app lists in setting, MOCK_UID1 should downgrade to NETWORK permission.
+ when(mDeps.getAppsAllowedOnRestrictedNetworks(any())).thenReturn(new ArraySet<>());
+ contentObserver.onChange(true /* selfChange */);
+ mNetdMonitor.expectPermission(NETWORK, new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1});
+
+ // MOCK_PACKAGE1 removed, should revoke permission from MOCK_UID1.
+ when(mPackageManager.getPackagesForUid(MOCK_UID1)).thenReturn(new String[]{MOCK_PACKAGE2});
+ removePackageForUsers(new UserHandle[]{MOCK_USER1}, MOCK_PACKAGE1, MOCK_UID1);
+ mNetdMonitor.expectNoPermission(new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1});
+ }
+}
\ No newline at end of file
diff --git a/packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java b/packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java
index fd374bc..c32c1d2 100644
--- a/packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java
+++ b/packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java
@@ -152,6 +152,8 @@
private static final String TEST_SSID = "AndroidAP";
private static NetworkTemplate sTemplateWifi = buildTemplateWifi(TEST_SSID);
+ private static NetworkTemplate sTemplateCarrierWifi1 =
+ buildTemplateWifi(NetworkTemplate.WIFI_NETWORKID_ALL, IMSI_1);
private static NetworkTemplate sTemplateImsi1 = buildTemplateMobileAll(IMSI_1);
private static NetworkTemplate sTemplateImsi2 = buildTemplateMobileAll(IMSI_2);
@@ -297,45 +299,82 @@
mHandlerThread.quitSafely();
}
- @Test
- public void testNetworkStatsWifi() throws Exception {
+ private void initWifiStats(NetworkStateSnapshot snapshot) throws Exception {
// pretend that wifi network comes online; service should ask about full
// network state, and poll any existing interfaces before updating.
expectDefaultSettings();
- NetworkStateSnapshot[] states = new NetworkStateSnapshot[] {buildWifiState()};
+ NetworkStateSnapshot[] states = new NetworkStateSnapshot[] {snapshot};
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
- mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states),
+ mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states),
new UnderlyingNetworkInfo[0]);
+ }
- // verify service has empty history for wifi
+ private void incrementWifiStats(long durationMillis, String iface,
+ long rxb, long rxp, long txb, long txp) throws Exception {
+ incrementCurrentTime(durationMillis);
+ expectDefaultSettings();
+ expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
+ .insertEntry(iface, rxb, rxp, txb, txp));
+ expectNetworkStatsUidDetail(buildEmptyStats());
+ forcePollAndWaitForIdle();
+ }
+
+ @Test
+ public void testNetworkStatsCarrierWifi() throws Exception {
+ initWifiStats(buildWifiState(true, TEST_IFACE, IMSI_1));
+ // verify service has empty history for carrier merged wifi and non-carrier wifi
+ assertNetworkTotal(sTemplateCarrierWifi1, 0L, 0L, 0L, 0L, 0);
assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0);
// modify some number on wifi, and trigger poll event
- incrementCurrentTime(HOUR_IN_MILLIS);
- expectDefaultSettings();
- expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
- .insertEntry(TEST_IFACE, 1024L, 1L, 2048L, 2L));
- expectNetworkStatsUidDetail(buildEmptyStats());
- forcePollAndWaitForIdle();
+ incrementWifiStats(HOUR_IN_MILLIS, TEST_IFACE, 1024L, 1L, 2048L, 2L);
// verify service recorded history
- assertNetworkTotal(sTemplateWifi, 1024L, 1L, 2048L, 2L, 0);
+ assertNetworkTotal(sTemplateCarrierWifi1, 1024L, 1L, 2048L, 2L, 0);
+
+ // verify service recorded history for wifi with SSID filter
+ assertNetworkTotal(sTemplateWifi, 1024L, 1L, 2048L, 2L, 0);
// and bump forward again, with counters going higher. this is
// important, since polling should correctly subtract last snapshot.
- incrementCurrentTime(DAY_IN_MILLIS);
- expectDefaultSettings();
- expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
- .insertEntry(TEST_IFACE, 4096L, 4L, 8192L, 8L));
- expectNetworkStatsUidDetail(buildEmptyStats());
- forcePollAndWaitForIdle();
+ incrementWifiStats(DAY_IN_MILLIS, TEST_IFACE, 4096L, 4L, 8192L, 8L);
+
+ // verify service recorded history
+ assertNetworkTotal(sTemplateCarrierWifi1, 4096L, 4L, 8192L, 8L, 0);
+ // verify service recorded history for wifi with SSID filter
+ assertNetworkTotal(sTemplateWifi, 4096L, 4L, 8192L, 8L, 0);
+ }
+
+ @Test
+ public void testNetworkStatsNonCarrierWifi() throws Exception {
+ initWifiStats(buildWifiState());
+
+ // verify service has empty history for wifi
+ assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0);
+ // verify service has empty history for carrier merged wifi
+ assertNetworkTotal(sTemplateCarrierWifi1, 0L, 0L, 0L, 0L, 0);
+
+ // modify some number on wifi, and trigger poll event
+ incrementWifiStats(HOUR_IN_MILLIS, TEST_IFACE, 1024L, 1L, 2048L, 2L);
+
+ // verify service recorded history
+ assertNetworkTotal(sTemplateWifi, 1024L, 1L, 2048L, 2L, 0);
+ // verify service has empty history for carrier wifi since current network is non carrier
+ // wifi
+ assertNetworkTotal(sTemplateCarrierWifi1, 0L, 0L, 0L, 0L, 0);
+
+ // and bump forward again, with counters going higher. this is
+ // important, since polling should correctly subtract last snapshot.
+ incrementWifiStats(DAY_IN_MILLIS, TEST_IFACE, 4096L, 4L, 8192L, 8L);
// verify service recorded history
assertNetworkTotal(sTemplateWifi, 4096L, 4L, 8192L, 8L, 0);
-
+ // verify service has empty history for carrier wifi since current network is non carrier
+ // wifi
+ assertNetworkTotal(sTemplateCarrierWifi1, 0L, 0L, 0L, 0L, 0);
}
@Test
@@ -349,7 +388,7 @@
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
- mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states),
+ mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states),
new UnderlyingNetworkInfo[0]);
// verify service has empty history for wifi
@@ -423,7 +462,7 @@
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
- mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states),
+ mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states),
new UnderlyingNetworkInfo[0]);
// modify some number on wifi, and trigger poll event
@@ -464,7 +503,7 @@
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
- mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states),
+ mService.notifyNetworkStatus(NETWORKS_MOBILE, states, getActiveIface(states),
new UnderlyingNetworkInfo[0]);
// create some traffic on first network
@@ -499,7 +538,7 @@
.insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L)
.insertEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 512L, 4L, 0L, 0L, 0L));
- mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states),
+ mService.notifyNetworkStatus(NETWORKS_MOBILE, states, getActiveIface(states),
new UnderlyingNetworkInfo[0]);
forcePollAndWaitForIdle();
@@ -539,7 +578,7 @@
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
- mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states),
+ mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states),
new UnderlyingNetworkInfo[0]);
// create some traffic
@@ -607,7 +646,7 @@
expectNetworkStatsUidDetail(buildEmptyStats());
setMobileRatTypeAndWaitForIdle(TelephonyManager.NETWORK_TYPE_UMTS);
- mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states),
+ mService.notifyNetworkStatus(NETWORKS_MOBILE, states, getActiveIface(states),
new UnderlyingNetworkInfo[0]);
// Create some traffic.
@@ -699,7 +738,7 @@
new int[]{NetworkCapabilities.NET_CAPABILITY_OEM_PAID})};
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
- mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states),
+ mService.notifyNetworkStatus(NETWORKS_MOBILE, states, getActiveIface(states),
new UnderlyingNetworkInfo[0]);
// Create some traffic.
@@ -714,7 +753,7 @@
new int[]{NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE})};
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
- mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states),
+ mService.notifyNetworkStatus(NETWORKS_MOBILE, states, getActiveIface(states),
new UnderlyingNetworkInfo[0]);
// Create some traffic.
@@ -730,7 +769,7 @@
NetworkCapabilities.NET_CAPABILITY_OEM_PAID})};
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
- mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states),
+ mService.notifyNetworkStatus(NETWORKS_MOBILE, states, getActiveIface(states),
new UnderlyingNetworkInfo[0]);
// Create some traffic.
@@ -744,7 +783,7 @@
states = new NetworkStateSnapshot[]{buildOemManagedMobileState(IMSI_1, false, new int[]{})};
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
- mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states),
+ mService.notifyNetworkStatus(NETWORKS_MOBILE, states, getActiveIface(states),
new UnderlyingNetworkInfo[0]);
// Create some traffic.
@@ -797,7 +836,7 @@
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
- mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states),
+ mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states),
new UnderlyingNetworkInfo[0]);
// create some traffic for two apps
@@ -856,7 +895,7 @@
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
- mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states),
+ mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states),
new UnderlyingNetworkInfo[0]);
NetworkStats.Entry entry1 = new NetworkStats.Entry(
@@ -900,7 +939,7 @@
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
- mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states),
+ mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states),
new UnderlyingNetworkInfo[0]);
NetworkStats.Entry uidStats = new NetworkStats.Entry(
@@ -931,7 +970,7 @@
// mStatsFactory#readNetworkStatsDetail() has the following invocations:
// 1) NetworkStatsService#systemReady from #setUp.
- // 2) mService#forceUpdateIfaces in the test above.
+ // 2) mService#notifyNetworkStatus in the test above.
//
// Additionally, we should have one call from the above call to mService#getDetailedUidStats
// with the augmented ifaceFilter.
@@ -955,7 +994,7 @@
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
- mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states),
+ mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states),
new UnderlyingNetworkInfo[0]);
// create some initial traffic
@@ -1013,7 +1052,7 @@
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
- mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states),
+ mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states),
new UnderlyingNetworkInfo[0]);
// create some initial traffic
@@ -1053,7 +1092,7 @@
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
- mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states),
+ mService.notifyNetworkStatus(NETWORKS_MOBILE, states, getActiveIface(states),
new UnderlyingNetworkInfo[0]);
// Create some traffic
@@ -1092,7 +1131,7 @@
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
- mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states),
+ mService.notifyNetworkStatus(NETWORKS_MOBILE, states, getActiveIface(states),
new UnderlyingNetworkInfo[0]);
// create some tethering traffic
@@ -1149,7 +1188,7 @@
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
- mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states),
+ mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states),
new UnderlyingNetworkInfo[0]);
// verify service has empty history for wifi
@@ -1255,7 +1294,7 @@
mService.registerNetworkStatsProvider("TEST", provider);
assertNotNull(cb);
- mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states),
+ mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states),
new UnderlyingNetworkInfo[0]);
// Verifies that one requestStatsUpdate will be called during iface update.
@@ -1320,7 +1359,7 @@
mService.registerNetworkStatsProvider("TEST", provider);
assertNotNull(cb);
- mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states),
+ mService.notifyNetworkStatus(NETWORKS_MOBILE, states, getActiveIface(states),
new UnderlyingNetworkInfo[0]);
// Verifies that one requestStatsUpdate will be called during iface update.
@@ -1378,7 +1417,7 @@
expectDefaultSettings();
NetworkStateSnapshot[] states =
new NetworkStateSnapshot[]{buildWifiState(true /* isMetered */, TEST_IFACE)};
- mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states),
+ mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states),
new UnderlyingNetworkInfo[0]);
// Register custom provider and retrieve callback.
@@ -1428,7 +1467,7 @@
// 3G network comes online.
setMobileRatTypeAndWaitForIdle(TelephonyManager.NETWORK_TYPE_UMTS);
- mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states),
+ mService.notifyNetworkStatus(NETWORKS_MOBILE, states, getActiveIface(states),
new UnderlyingNetworkInfo[0]);
// Create some traffic.
@@ -1450,7 +1489,8 @@
setCombineSubtypeEnabled(true);
// Call handleOnCollapsedRatTypeChanged manually to simulate the callback fired
- // when stopping monitor, this is needed by NetworkStatsService to trigger updateIfaces.
+ // when stopping monitor, this is needed by NetworkStatsService to trigger
+ // handleNotifyNetworkStatus.
mService.handleOnCollapsedRatTypeChanged();
HandlerUtils.waitForIdle(mHandlerThread, WAIT_TIMEOUT);
// Create some traffic.
@@ -1499,7 +1539,7 @@
NetworkStateSnapshot[] states = new NetworkStateSnapshot[]{
buildWifiState(true /*isMetered*/, TEST_IFACE2), buildMobile3gState(IMSI_1)};
expectNetworkStatsUidDetail(buildEmptyStats());
- mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states),
+ mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states),
new UnderlyingNetworkInfo[0]);
// Create some traffic on mobile network.
@@ -1661,10 +1701,15 @@
}
private static NetworkStateSnapshot buildWifiState() {
- return buildWifiState(false, TEST_IFACE);
+ return buildWifiState(false, TEST_IFACE, null);
}
private static NetworkStateSnapshot buildWifiState(boolean isMetered, @NonNull String iface) {
+ return buildWifiState(isMetered, iface, null);
+ }
+
+ private static NetworkStateSnapshot buildWifiState(boolean isMetered, @NonNull String iface,
+ String subscriberId) {
final LinkProperties prop = new LinkProperties();
prop.setInterfaceName(iface);
final NetworkCapabilities capabilities = new NetworkCapabilities();
@@ -1672,7 +1717,7 @@
capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING, true);
capabilities.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
capabilities.setSSID(TEST_SSID);
- return new NetworkStateSnapshot(WIFI_NETWORK, capabilities, prop, null, TYPE_WIFI);
+ return new NetworkStateSnapshot(WIFI_NETWORK, capabilities, prop, subscriberId, TYPE_WIFI);
}
private static NetworkStateSnapshot buildMobile3gState(String subscriberId) {
diff --git a/packages/SettingsLib/ActionButtonsPreference/lint-baseline.xml b/packages/SettingsLib/ActionButtonsPreference/lint-baseline.xml
index a19f7af..22b25a3 100644
--- a/packages/SettingsLib/ActionButtonsPreference/lint-baseline.xml
+++ b/packages/SettingsLib/ActionButtonsPreference/lint-baseline.xml
@@ -23,4 +23,15 @@
column="15"/>
</issue>
+ <issue
+ id="NewApi"
+ message="`?android:attr/dialogCornerRadius` requires API level 28 (current min is 21)"
+ errorLine1=" android:radius="?android:attr/dialogCornerRadius""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SettingsLib/ActionButtonsPreference/res/drawable/settingslib_rounded_background.xml"
+ line="23"
+ column="9"/>
+ </issue>
+
</issues>
diff --git a/packages/SettingsLib/ActionButtonsPreference/res/drawable/settingslib_rounded_background.xml b/packages/SettingsLib/ActionButtonsPreference/res/drawable/settingslib_rounded_background.xml
new file mode 100644
index 0000000..ae3834d
--- /dev/null
+++ b/packages/SettingsLib/ActionButtonsPreference/res/drawable/settingslib_rounded_background.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ android:shape="rectangle">
+ <solid android:color="?androidprv:attr/colorSurface" />
+ <corners
+ android:radius="?android:attr/dialogCornerRadius"
+ />
+</shape>
\ No newline at end of file
diff --git a/packages/SettingsLib/ActionButtonsPreference/res/layout-v31/settingslib_action_buttons.xml b/packages/SettingsLib/ActionButtonsPreference/res/layout-v31/settingslib_action_buttons.xml
new file mode 100644
index 0000000..ba612d7
--- /dev/null
+++ b/packages/SettingsLib/ActionButtonsPreference/res/layout-v31/settingslib_action_buttons.xml
@@ -0,0 +1,78 @@
+<?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.
+ -->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_margin="8dp"
+ android:paddingHorizontal="8dp"
+ android:orientation="horizontal"
+ android:background="@drawable/settingslib_rounded_background">
+
+ <Button
+ android:id="@+id/button1"
+ style="@style/SettingsLibActionButton"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"/>
+
+ <View
+ android:id="@+id/divider1"
+ android:layout_width="1dp"
+ android:layout_height="match_parent"
+ android:paddingHorizontal="4dp"
+ android:visibility="gone"
+ android:background="?android:colorBackground" />
+
+ <Button
+ android:id="@+id/button2"
+ style="@style/SettingsLibActionButton"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"/>
+
+ <View
+ android:id="@+id/divider2"
+ android:layout_width="1dp"
+ android:layout_height="match_parent"
+ android:paddingHorizontal="4dp"
+ android:visibility="gone"
+ android:background="?android:colorBackground" />
+
+ <Button
+ android:id="@+id/button3"
+ style="@style/SettingsLibActionButton"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"/>
+
+ <View
+ android:id="@+id/divider3"
+ android:layout_width="1dp"
+ android:layout_height="match_parent"
+ android:paddingHorizontal="4dp"
+ android:visibility="gone"
+ android:background="?android:colorBackground" />
+
+ <Button
+ android:id="@+id/button4"
+ style="@style/SettingsLibActionButton"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"/>
+</LinearLayout>
diff --git a/packages/SettingsLib/ActionButtonsPreference/res/layout/settings_action_buttons.xml b/packages/SettingsLib/ActionButtonsPreference/res/layout/settingslib_action_buttons.xml
similarity index 88%
rename from packages/SettingsLib/ActionButtonsPreference/res/layout/settings_action_buttons.xml
rename to packages/SettingsLib/ActionButtonsPreference/res/layout/settingslib_action_buttons.xml
index 4f47113..55df34f 100644
--- a/packages/SettingsLib/ActionButtonsPreference/res/layout/settings_action_buttons.xml
+++ b/packages/SettingsLib/ActionButtonsPreference/res/layout/settingslib_action_buttons.xml
@@ -24,29 +24,29 @@
<Button
android:id="@+id/button1"
- style="@style/SettingsActionButton"
+ style="@style/SettingsLibActionButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"/>
<Button
android:id="@+id/button2"
- style="@style/SettingsActionButton"
+ style="@style/SettingsLibActionButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"/>
<Button
android:id="@+id/button3"
- style="@style/SettingsActionButton"
+ style="@style/SettingsLibActionButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"/>
<Button
android:id="@+id/button4"
- style="@style/SettingsActionButton"
+ style="@style/SettingsLibActionButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"/>
-</LinearLayout>
\ No newline at end of file
+</LinearLayout>
diff --git a/packages/SettingsLib/ActionButtonsPreference/res/values/styles.xml b/packages/SettingsLib/ActionButtonsPreference/res/values/styles.xml
index efa508d..42c7d76 100644
--- a/packages/SettingsLib/ActionButtonsPreference/res/values/styles.xml
+++ b/packages/SettingsLib/ActionButtonsPreference/res/values/styles.xml
@@ -16,11 +16,10 @@
-->
<resources>
- <style name="SettingsActionButton" parent="android:Widget.DeviceDefault.Button.Borderless.Colored">
+ <style name="SettingsLibActionButton" parent="android:Widget.DeviceDefault.Button.Borderless.Colored">
<item name="android:drawablePadding">4dp</item>
<item name="android:drawableTint">@*android:color/btn_colored_borderless_text_material</item>
- <item name="android:layout_marginEnd">8dp</item>
<item name="android:paddingTop">20dp</item>
<item name="android:paddingBottom">20dp</item>
</style>
-</resources>
\ No newline at end of file
+</resources>
diff --git a/packages/SettingsLib/ActionButtonsPreference/src/com/android/settingslib/widget/ActionButtonsPreference.java b/packages/SettingsLib/ActionButtonsPreference/src/com/android/settingslib/widget/ActionButtonsPreference.java
index 8b46cc6..aeda7ac 100644
--- a/packages/SettingsLib/ActionButtonsPreference/src/com/android/settingslib/widget/ActionButtonsPreference.java
+++ b/packages/SettingsLib/ActionButtonsPreference/src/com/android/settingslib/widget/ActionButtonsPreference.java
@@ -27,16 +27,20 @@
import androidx.annotation.DrawableRes;
import androidx.annotation.StringRes;
+import androidx.core.os.BuildCompat;
import androidx.preference.Preference;
import androidx.preference.PreferenceViewHolder;
+import java.util.ArrayList;
+import java.util.List;
+
/**
* This preference provides a four buttons layout with Settings style.
* It looks like below
*
- * --------------------------------------------------
- * button1 | button2 | button3 | button4 |
- * --------------------------------------------------
+ * ---------------------------------------
+ * - button1 | button2 | button3 | button4 -
+ * ---------------------------------------
*
* User can set title / icon / click listener for each button.
*
@@ -49,10 +53,16 @@
public class ActionButtonsPreference extends Preference {
private static final String TAG = "ActionButtonPreference";
+
private final ButtonInfo mButton1Info = new ButtonInfo();
private final ButtonInfo mButton2Info = new ButtonInfo();
private final ButtonInfo mButton3Info = new ButtonInfo();
private final ButtonInfo mButton4Info = new ButtonInfo();
+ private final List<ButtonInfo> mVisibleButtonInfos = new ArrayList<>(4);
+
+ private View mDivider1;
+ private View mDivider2;
+ private View mDivider3;
public ActionButtonsPreference(Context context, AttributeSet attrs,
int defStyleAttr, int defStyleRes) {
@@ -76,25 +86,49 @@
}
private void init() {
- setLayoutResource(R.layout.settings_action_buttons);
+ setLayoutResource(R.layout.settingslib_action_buttons);
setSelectable(false);
}
@Override
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
- holder.setDividerAllowedAbove(true);
- holder.setDividerAllowedBelow(true);
+ if (!BuildCompat.isAtLeastS()) {
+ holder.setDividerAllowedAbove(true);
+ holder.setDividerAllowedBelow(true);
+ }
mButton1Info.mButton = (Button) holder.findViewById(R.id.button1);
mButton2Info.mButton = (Button) holder.findViewById(R.id.button2);
mButton3Info.mButton = (Button) holder.findViewById(R.id.button3);
mButton4Info.mButton = (Button) holder.findViewById(R.id.button4);
+ mDivider1 = holder.findViewById(R.id.divider1);
+ mDivider2 = holder.findViewById(R.id.divider2);
+ mDivider3 = holder.findViewById(R.id.divider3);
+
mButton1Info.setUpButton();
mButton2Info.setUpButton();
mButton3Info.setUpButton();
mButton4Info.setUpButton();
+
+ // Add visible button into list only
+ if (mButton1Info.isVisible()) {
+ mVisibleButtonInfos.add(mButton1Info);
+ }
+ if (mButton2Info.isVisible()) {
+ mVisibleButtonInfos.add(mButton2Info);
+ }
+ if (mButton3Info.isVisible()) {
+ mVisibleButtonInfos.add(mButton3Info);
+ }
+ if (mButton4Info.isVisible()) {
+ mVisibleButtonInfos.add(mButton4Info);
+ }
+
+ setupDivider1();
+ setupDivider2();
+ setupDivider3();
}
/**
@@ -357,6 +391,28 @@
return this;
}
+ private void setupDivider1() {
+ // Display divider1 only if button1 and button2 is visible
+ if (mDivider1 != null && mButton1Info.isVisible() && mButton2Info.isVisible()) {
+ mDivider1.setVisibility(View.VISIBLE);
+ }
+ }
+
+ private void setupDivider2() {
+ // Display divider2 only if button3 is visible and button2 or button3 is visible
+ if (mDivider2 != null && mButton3Info.isVisible()
+ && (mButton1Info.isVisible() || mButton2Info.isVisible())) {
+ mDivider2.setVisibility(View.VISIBLE);
+ }
+ }
+
+ private void setupDivider3() {
+ // Display divider3 only if button4 is visible and 2 visible buttons at least
+ if (mDivider3 != null && mVisibleButtonInfos.size() > 1 && mButton4Info.isVisible()) {
+ mDivider3.setVisibility(View.VISIBLE);
+ }
+ }
+
static class ButtonInfo {
private Button mButton;
private CharSequence mText;
@@ -379,6 +435,10 @@
}
}
+ boolean isVisible() {
+ return mButton.getVisibility() == View.VISIBLE;
+ }
+
/**
* By default, four buttons are visible.
* However, there are two cases which button should be invisible.
diff --git a/packages/SettingsLib/AppPreference/res/layout/preference_app.xml b/packages/SettingsLib/AppPreference/res/layout/preference_app.xml
index 0390e86..4907c6f 100644
--- a/packages/SettingsLib/AppPreference/res/layout/preference_app.xml
+++ b/packages/SettingsLib/AppPreference/res/layout/preference_app.xml
@@ -54,7 +54,7 @@
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:fadingEdge="horizontal"
- android:singleLine="true"
+ android:maxLines="2"
android:textAppearance="?android:attr/textAppearanceListItem"/>
<TextView
diff --git a/packages/SettingsLib/BannerMessagePreference/Android.bp b/packages/SettingsLib/BannerMessagePreference/Android.bp
index 82e837b..c6a9562 100644
--- a/packages/SettingsLib/BannerMessagePreference/Android.bp
+++ b/packages/SettingsLib/BannerMessagePreference/Android.bp
@@ -14,9 +14,10 @@
resource_dirs: ["res"],
static_libs: [
- "androidx.preference_preference",
+ "androidx.preference_preference",
+ "SettingsLibSettingsTheme",
],
sdk_version: "system_current",
- min_sdk_version: "21",
+ min_sdk_version: "28",
}
diff --git a/packages/SettingsLib/BannerMessagePreference/AndroidManifest.xml b/packages/SettingsLib/BannerMessagePreference/AndroidManifest.xml
index 56b886f..dd51ea3 100644
--- a/packages/SettingsLib/BannerMessagePreference/AndroidManifest.xml
+++ b/packages/SettingsLib/BannerMessagePreference/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/BannerMessagePreference/lint-baseline.xml b/packages/SettingsLib/BannerMessagePreference/lint-baseline.xml
deleted file mode 100644
index ba02a1f..0000000
--- a/packages/SettingsLib/BannerMessagePreference/lint-baseline.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.1.0" client="cli" variant="all" version="4.1.0">
-
- <issue
- id="NewApi"
- message="`@android:style/Widget.DeviceDefault.Button.Borderless.Colored` requires API level 28 (current min is 21)"
- errorLine1=" style="@android:style/Widget.DeviceDefault.Button.Borderless.Colored"/>"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="frameworks/base/packages/SettingsLib/BannerMessagePreference/res/layout/banner_message.xml"
- line="65"
- column="13"/>
- </issue>
-
- <issue
- id="NewApi"
- message="`@android:style/Widget.DeviceDefault.Button.Borderless.Colored` requires API level 28 (current min is 21)"
- errorLine1=" style="@android:style/Widget.DeviceDefault.Button.Borderless.Colored"/>"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="frameworks/base/packages/SettingsLib/BannerMessagePreference/res/layout/banner_message.xml"
- line="71"
- column="13"/>
- </issue>
-
- <issue
- id="NewApi"
- message="`?android:attr/colorError` requires API level 26 (current min is 21)"
- errorLine1=" android:fillColor="?android:attr/colorError""
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="frameworks/base/packages/SettingsLib/BannerMessagePreference/res/drawable/ic_warning.xml"
- line="24"
- column="9"/>
- </issue>
-
-</issues>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/drawable-v31/settingslib_card_background.xml b/packages/SettingsLib/BannerMessagePreference/res/drawable-v31/settingslib_card_background.xml
new file mode 100644
index 0000000..072eb58
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/drawable-v31/settingslib_card_background.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <solid android:color="?android:attr/background" />
+ <corners android:radius="28dp"/>
+</shape>
\ No newline at end of file
diff --git a/packages/SettingsLib/BannerMessagePreference/res/drawable-v31/settingslib_ic_cross.xml b/packages/SettingsLib/BannerMessagePreference/res/drawable-v31/settingslib_ic_cross.xml
new file mode 100644
index 0000000..d926cc6
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/drawable-v31/settingslib_ic_cross.xml
@@ -0,0 +1,25 @@
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:fillColor="?android:attr/textColorSecondary"
+ android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12 19,6.41z"/>
+</vector>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/layout-v31/settingslib_banner_message.xml b/packages/SettingsLib/BannerMessagePreference/res/layout-v31/settingslib_banner_message.xml
new file mode 100644
index 0000000..904b78c
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/layout-v31/settingslib_banner_message.xml
@@ -0,0 +1,90 @@
+<?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.
+ -->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ style="@style/Banner.Preference.SettingsLib">
+
+ <RelativeLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingBottom="8dp"
+ android:orientation="horizontal">
+
+ <ImageView
+ android:id="@+id/banner_icon"
+ android:layout_width="24dp"
+ android:layout_height="24dp"
+ android:layout_alignParentStart="true"
+ android:importantForAccessibility="no" />
+
+ <ImageButton
+ android:id="@+id/banner_dismiss_btn"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/settingslib_ic_cross"
+ android:layout_alignParentEnd="true"
+ android:contentDescription="@string/accessibility_banner_message_dismiss"
+ style="@style/Banner.Dismiss.SettingsLib" />
+ </RelativeLayout>
+
+ <TextView
+ android:id="@+id/banner_title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingBottom="4dp"
+ android:textAppearance="@style/Banner.Title.SettingsLib"/>
+
+ <TextView
+ android:id="@+id/banner_subtitle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingBottom="4dp"
+ android:textAppearance="@style/Banner.Subtitle.SettingsLib"
+ android:visibility="gone"/>
+
+ <TextView
+ android:id="@+id/banner_summary"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingTop="4dp"
+ android:paddingBottom="8dp"
+ android:textAppearance="@style/Banner.Summary.SettingsLib"/>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:minHeight="8dp"
+ android:gravity="end">
+
+ <Button
+ android:id="@+id/banner_negative_btn"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ style="@style/Banner.ButtonText.SettingsLib"/>
+
+ <Button
+ android:id="@+id/banner_positive_btn"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ style="@style/Banner.ButtonText.SettingsLib"/>
+ </LinearLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/packages/SettingsLib/BannerMessagePreference/res/layout/banner_message.xml b/packages/SettingsLib/BannerMessagePreference/res/layout/settingslib_banner_message.xml
similarity index 81%
rename from packages/SettingsLib/BannerMessagePreference/res/layout/banner_message.xml
rename to packages/SettingsLib/BannerMessagePreference/res/layout/settingslib_banner_message.xml
index 977e196..80cb1d5 100644
--- a/packages/SettingsLib/BannerMessagePreference/res/layout/banner_message.xml
+++ b/packages/SettingsLib/BannerMessagePreference/res/layout/settingslib_banner_message.xml
@@ -30,8 +30,10 @@
android:orientation="horizontal">
<ImageView
+ android:id="@+id/banner_icon"
android:layout_width="24dp"
android:layout_height="24dp"
+ android:importantForAccessibility="no"
android:src="@drawable/ic_warning"/>
<LinearLayout
@@ -70,4 +72,19 @@
android:layout_height="wrap_content"
style="@android:style/Widget.DeviceDefault.Button.Borderless.Colored"/>
</LinearLayout>
+
+ <!-- Not supported before v31 -->
+ <TextView
+ android:id="@+id/banner_subtitle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:visibility="gone"/>
+
+ <!-- Not supported before v31 -->
+ <ImageButton
+ android:id="@+id/banner_dismiss_btn"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:contentDescription="@string/accessibility_banner_message_dismiss"
+ android:visibility="gone"/>
</LinearLayout>
\ No newline at end of file
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-night/colors.xml b/packages/SettingsLib/BannerMessagePreference/res/values-night/colors.xml
new file mode 100644
index 0000000..50141a8
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-night/colors.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources>
+ <color name="banner_background_attention_high">#3B2D2C</color> <!-- red card background -->
+ <color name="banner_background_attention_medium">#333121</color> <!-- yellow card background -->
+ <color name="banner_background_attention_low">#2B3328</color> <!-- green card background -->
+ <color name="banner_accent_attention_high">#F28B82</color> <!-- red accent color -->
+ <color name="banner_accent_attention_medium">#FDD663</color> <!-- yellow accent color -->
+ <color name="banner_accent_attention_low">#81C995</color> <!-- green accent color -->
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-v31/styles.xml b/packages/SettingsLib/BannerMessagePreference/res/values-v31/styles.xml
new file mode 100644
index 0000000..a39e779
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-v31/styles.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <style name="Banner.Preference.SettingsLib"
+ parent="android:Widget.DeviceDefault">
+ <item name="android:paddingStart">20dp</item>
+ <item name="android:paddingEnd">20dp</item>
+ <item name="android:paddingTop">20dp</item>
+ <item name="android:paddingBottom">8dp</item>
+ <item name="android:layout_marginTop">8dp</item>
+ <item name="android:layout_marginStart">16dp</item>
+ <item name="android:layout_marginBottom">8dp</item>
+ <item name="android:layout_marginEnd">16dp</item>
+ <item name="android:background">@drawable/settingslib_card_background</item>
+ </style>
+
+ <style name="Banner.Title.SettingsLib"
+ parent="@android:style/TextAppearance.Material.Subhead">
+ <item name="android:textSize">20sp</item>
+ <item name="android:fontFamily">@*android:string/config_headlineFontFamilyMedium</item>
+ <item name="android:textColor">?android:attr/textColorPrimary</item>
+ </style>
+
+ <style name="Banner.Subtitle.SettingsLib"
+ parent="@*android:style/TextAppearance.DeviceDefault.Body1">
+ <item name="android:textColor">?android:attr/textColorSecondary</item>
+ <item name="android:textSize">14sp</item>
+ </style>
+
+ <style name="Banner.Summary.SettingsLib"
+ parent="@*android:style/TextAppearance.DeviceDefault.Body1">
+ <item name="android:textColor">?android:attr/textColorSecondary</item>
+ <item name="android:textSize">14sp</item>
+ </style>
+
+ <style name="Banner.Dismiss.SettingsLib"
+ parent="android:Widget.DeviceDefault.ImageButton">
+ <item name="android:background">@android:color/transparent</item>
+ </style>
+
+ <style name="Banner.ButtonText.SettingsLib"
+ parent="android:Widget.DeviceDefault.Button.Borderless.Colored">
+ <item name="android:textColor">?android:attr/colorAccent</item>
+ </style>
+</resources>
\ No newline at end of file
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values/attrs.xml b/packages/SettingsLib/BannerMessagePreference/res/values/attrs.xml
new file mode 100644
index 0000000..96634a5
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values/attrs.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources>
+ <declare-styleable name="BannerMessagePreference">
+ <attr format="enum" name="attentionLevel">
+ <enum name="high" value="0"/>
+ <enum name="medium" value="1"/>
+ <enum name="low" value="2"/>
+ </attr>
+ <attr format="string" name="subtitle" />
+ </declare-styleable>
+</resources>
\ No newline at end of file
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values/colors.xml b/packages/SettingsLib/BannerMessagePreference/res/values/colors.xml
new file mode 100644
index 0000000..53d72d1
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values/colors.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources>
+ <color name="banner_background_attention_high">#FFDAD5</color> <!-- red card background -->
+ <color name="banner_background_attention_medium">#F0E3A8</color> <!-- yellow card background -->
+ <color name="banner_background_attention_low">#CFEBC0</color> <!-- green card background -->
+ <color name="banner_accent_attention_high">#BB3322</color> <!-- red accent color -->
+ <color name="banner_accent_attention_medium">#895900</color> <!-- yellow accent color -->
+ <color name="banner_accent_attention_low">#1D7233</color> <!-- green accent color -->
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values/strings.xml
new file mode 100644
index 0000000..a1af38a
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+ <!-- Content description of the dismiss button on a banner message for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_banner_message_dismiss">Dismiss</string>
+</resources>
+
+
diff --git a/packages/SettingsLib/BannerMessagePreference/src/com/android/settingslib/widget/BannerMessagePreference.java b/packages/SettingsLib/BannerMessagePreference/src/com/android/settingslib/widget/BannerMessagePreference.java
index 5352552..5bedd7a1 100644
--- a/packages/SettingsLib/BannerMessagePreference/src/com/android/settingslib/widget/BannerMessagePreference.java
+++ b/packages/SettingsLib/BannerMessagePreference/src/com/android/settingslib/widget/BannerMessagePreference.java
@@ -17,13 +17,25 @@
package com.android.settingslib.widget;
import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
+import android.graphics.drawable.Drawable;
+import android.os.Build;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;
import android.widget.Button;
+import android.widget.ImageButton;
+import android.widget.ImageView;
import android.widget.TextView;
+import androidx.annotation.ColorInt;
+import androidx.annotation.ColorRes;
+import androidx.annotation.RequiresApi;
import androidx.annotation.StringRes;
+import androidx.core.os.BuildCompat;
import androidx.preference.Preference;
import androidx.preference.PreferenceViewHolder;
@@ -33,55 +45,151 @@
*/
public class BannerMessagePreference extends Preference {
+ public enum AttentionLevel {
+ HIGH(0, R.color.banner_background_attention_high, R.color.banner_accent_attention_high),
+ MEDIUM(1,
+ R.color.banner_background_attention_medium,
+ R.color.banner_accent_attention_medium),
+ LOW(2, R.color.banner_background_attention_low, R.color.banner_accent_attention_low);
+
+ // Corresponds to the enum valye of R.attr.attentionLevel
+ private final int mAttrValue;
+ @ColorRes private final int mBackgroundColorResId;
+ @ColorRes private final int mAccentColorResId;
+
+ AttentionLevel(int attrValue, @ColorRes int backgroundColorResId,
+ @ColorRes int accentColorResId) {
+ mAttrValue = attrValue;
+ mBackgroundColorResId = backgroundColorResId;
+ mAccentColorResId = accentColorResId;
+ }
+
+ static AttentionLevel fromAttr(int attrValue) {
+ for (AttentionLevel level : values()) {
+ if (level.mAttrValue == attrValue) {
+ return level;
+ }
+ }
+ throw new IllegalArgumentException();
+ }
+
+ @ColorRes int getAccentColorResId() {
+ return mAccentColorResId;
+ }
+
+ @ColorRes int getBackgroundColorResId() {
+ return mBackgroundColorResId;
+ }
+ }
+
private static final String TAG = "BannerPreference";
- private BannerMessagePreference.ButtonInfo mPositiveButtonInfo;
- private BannerMessagePreference.ButtonInfo mNegativeButtonInfo;
+ private static final boolean IS_AT_LEAST_S = BuildCompat.isAtLeastS();
+
+ private final BannerMessagePreference.ButtonInfo mPositiveButtonInfo =
+ new BannerMessagePreference.ButtonInfo();
+ private final BannerMessagePreference.ButtonInfo mNegativeButtonInfo =
+ new BannerMessagePreference.ButtonInfo();
+ private final BannerMessagePreference.DismissButtonInfo mDismissButtonInfo =
+ new BannerMessagePreference.DismissButtonInfo();
+
+ // Default attention level is High.
+ private AttentionLevel mAttentionLevel = AttentionLevel.HIGH;
+ private String mSubtitle;
public BannerMessagePreference(Context context) {
super(context);
- init();
+ init(context, null /* attrs */);
}
public BannerMessagePreference(Context context, AttributeSet attrs) {
super(context, attrs);
- init();
+ init(context, attrs);
}
public BannerMessagePreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
- init();
+ init(context, attrs);
}
public BannerMessagePreference(Context context, AttributeSet attrs, int defStyleAttr,
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
- init();
+ init(context, attrs);
+ }
+
+ private void init(Context context, AttributeSet attrs) {
+ setSelectable(false);
+ setLayoutResource(R.layout.settingslib_banner_message);
+
+ if (IS_AT_LEAST_S) {
+ if (attrs != null) {
+ // Get attention level and subtitle from layout XML
+ TypedArray a =
+ context.obtainStyledAttributes(attrs, R.styleable.BannerMessagePreference);
+ int mAttentionLevelValue =
+ a.getInt(R.styleable.BannerMessagePreference_attentionLevel, 0);
+ mAttentionLevel = AttentionLevel.fromAttr(mAttentionLevelValue);
+ mSubtitle = a.getString(R.styleable.BannerMessagePreference_subtitle);
+ a.recycle();
+ }
+ }
}
@Override
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
- holder.setDividerAllowedAbove(true);
- holder.setDividerAllowedBelow(true);
+ final Context context = getContext();
+
+ final TextView titleView = (TextView) holder.findViewById(R.id.banner_title);
+ CharSequence title = getTitle();
+ titleView.setText(title);
+ titleView.setVisibility(title == null ? View.GONE : View.VISIBLE);
+
+ final TextView summaryView = (TextView) holder.findViewById(R.id.banner_summary);
+ summaryView.setText(getSummary());
mPositiveButtonInfo.mButton = (Button) holder.findViewById(R.id.banner_positive_btn);
mNegativeButtonInfo.mButton = (Button) holder.findViewById(R.id.banner_negative_btn);
+ if (IS_AT_LEAST_S) {
+ final Resources.Theme theme = context.getTheme();
+ @ColorInt final int accentColor =
+ context.getResources().getColor(mAttentionLevel.getAccentColorResId(), theme);
+ @ColorInt final int backgroundColor =
+ context.getResources().getColor(
+ mAttentionLevel.getBackgroundColorResId(), theme);
+
+ holder.setDividerAllowedAbove(false);
+ holder.setDividerAllowedBelow(false);
+ holder.itemView.getBackground().setTint(backgroundColor);
+
+ mPositiveButtonInfo.mColor = accentColor;
+ mNegativeButtonInfo.mColor = accentColor;
+
+ mDismissButtonInfo.mButton = (ImageButton) holder.findViewById(R.id.banner_dismiss_btn);
+ mDismissButtonInfo.setUpButton();
+
+ final TextView subtitleView = (TextView) holder.findViewById(R.id.banner_subtitle);
+ subtitleView.setText(mSubtitle);
+ subtitleView.setVisibility(mSubtitle == null ? View.GONE : View.VISIBLE);
+
+ final ImageView iconView = (ImageView) holder.findViewById(R.id.banner_icon);
+ if (iconView != null) {
+ Drawable icon = getIcon();
+ iconView.setImageDrawable(
+ icon == null
+ ? getContext().getDrawable(R.drawable.ic_warning)
+ : icon);
+ iconView.setColorFilter(
+ new PorterDuffColorFilter(accentColor, PorterDuff.Mode.SRC_IN));
+ }
+ } else {
+ holder.setDividerAllowedAbove(true);
+ holder.setDividerAllowedBelow(true);
+ }
+
mPositiveButtonInfo.setUpButton();
mNegativeButtonInfo.setUpButton();
-
- final TextView titleView = (TextView) holder.findViewById(R.id.banner_title);
- final TextView summaryView = (TextView) holder.findViewById(R.id.banner_summary);
-
- titleView.setText(getTitle());
- summaryView.setText(getSummary());
- }
-
- private void init() {
- mPositiveButtonInfo = new BannerMessagePreference.ButtonInfo();
- mNegativeButtonInfo = new BannerMessagePreference.ButtonInfo();
- setSelectable(false);
- setLayoutResource(R.layout.banner_message);
}
/**
@@ -107,6 +215,18 @@
}
/**
+ * Set the visibility state of dismiss button.
+ */
+ @RequiresApi(Build.VERSION_CODES.S)
+ public BannerMessagePreference setDismissButtonVisible(boolean isVisible) {
+ if (isVisible != mDismissButtonInfo.mIsVisible) {
+ mDismissButtonInfo.mIsVisible = isVisible;
+ notifyChanged();
+ }
+ return this;
+ }
+
+ /**
* Register a callback to be invoked when positive button is clicked.
*/
public BannerMessagePreference setPositiveButtonOnClickListener(
@@ -131,12 +251,31 @@
}
/**
+ * Register a callback to be invoked when the dismiss button is clicked.
+ */
+ @RequiresApi(Build.VERSION_CODES.S)
+ public BannerMessagePreference setDismissButtonOnClickListener(
+ View.OnClickListener listener) {
+ if (listener != mDismissButtonInfo.mListener) {
+ mDismissButtonInfo.mListener = listener;
+ notifyChanged();
+ }
+ return this;
+ }
+
+ /**
* Sets the text to be displayed in positive button.
*/
public BannerMessagePreference setPositiveButtonText(@StringRes int textResId) {
- final String newText = getContext().getString(textResId);
- if (!TextUtils.equals(newText, mPositiveButtonInfo.mText)) {
- mPositiveButtonInfo.mText = newText;
+ return setPositiveButtonText(getContext().getString(textResId));
+ }
+
+ /**
+ * Sets the text to be displayed in positive button.
+ */
+ public BannerMessagePreference setPositiveButtonText(String positiveButtonText) {
+ if (!TextUtils.equals(positiveButtonText, mPositiveButtonInfo.mText)) {
+ mPositiveButtonInfo.mText = positiveButtonText;
notifyChanged();
}
return this;
@@ -146,9 +285,51 @@
* Sets the text to be displayed in negative button.
*/
public BannerMessagePreference setNegativeButtonText(@StringRes int textResId) {
- final String newText = getContext().getString(textResId);
- if (!TextUtils.equals(newText, mNegativeButtonInfo.mText)) {
- mNegativeButtonInfo.mText = newText;
+ return setNegativeButtonText(getContext().getString(textResId));
+ }
+
+ /**
+ * Sets the text to be displayed in negative button.
+ */
+ public BannerMessagePreference setNegativeButtonText(String negativeButtonText) {
+ if (!TextUtils.equals(negativeButtonText, mNegativeButtonInfo.mText)) {
+ mNegativeButtonInfo.mText = negativeButtonText;
+ notifyChanged();
+ }
+ return this;
+ }
+
+ /**
+ * Sets the subtitle.
+ */
+ @RequiresApi(Build.VERSION_CODES.S)
+ public BannerMessagePreference setSubtitle(@StringRes int textResId) {
+ return setSubtitle(getContext().getString(textResId));
+ }
+
+ /**
+ * Sets the subtitle.
+ */
+ @RequiresApi(Build.VERSION_CODES.S)
+ public BannerMessagePreference setSubtitle(String subtitle) {
+ if (!TextUtils.equals(subtitle, mSubtitle)) {
+ mSubtitle = subtitle;
+ notifyChanged();
+ }
+ return this;
+ }
+
+ /**
+ * Sets the attention level. This will update the color theme of the preference.
+ */
+ @RequiresApi(Build.VERSION_CODES.S)
+ public BannerMessagePreference setAttentionLevel(AttentionLevel attentionLevel) {
+ if (attentionLevel == mAttentionLevel) {
+ return this;
+ }
+
+ if (attentionLevel != null) {
+ mAttentionLevel = attentionLevel;
notifyChanged();
}
return this;
@@ -159,11 +340,16 @@
private CharSequence mText;
private View.OnClickListener mListener;
private boolean mIsVisible = true;
+ @ColorInt private int mColor;
void setUpButton() {
mButton.setText(mText);
mButton.setOnClickListener(mListener);
+ if (IS_AT_LEAST_S) {
+ mButton.setTextColor(mColor);
+ }
+
if (shouldBeVisible()) {
mButton.setVisibility(View.VISIBLE);
} else {
@@ -179,4 +365,26 @@
return mIsVisible && (!TextUtils.isEmpty(mText));
}
}
+
+ static class DismissButtonInfo {
+ private ImageButton mButton;
+ private View.OnClickListener mListener;
+ private boolean mIsVisible = true;
+
+ void setUpButton() {
+ mButton.setOnClickListener(mListener);
+ if (shouldBeVisible()) {
+ mButton.setVisibility(View.VISIBLE);
+ } else {
+ mButton.setVisibility(View.GONE);
+ }
+ }
+
+ /**
+ * By default, dismiss button is visible if it has a click listener.
+ */
+ private boolean shouldBeVisible() {
+ return mIsVisible && (mListener != null);
+ }
+ }
}
diff --git a/packages/SettingsLib/CollapsingToolbarBaseActivity/src/com/android/settingslib/collapsingtoolbar/CollapsingToolbarBaseActivity.java b/packages/SettingsLib/CollapsingToolbarBaseActivity/src/com/android/settingslib/collapsingtoolbar/CollapsingToolbarBaseActivity.java
index 83a838f..e6ca2e0 100644
--- a/packages/SettingsLib/CollapsingToolbarBaseActivity/src/com/android/settingslib/collapsingtoolbar/CollapsingToolbarBaseActivity.java
+++ b/packages/SettingsLib/CollapsingToolbarBaseActivity/src/com/android/settingslib/collapsingtoolbar/CollapsingToolbarBaseActivity.java
@@ -35,7 +35,6 @@
public class CollapsingToolbarBaseActivity extends SettingsTransitionActivity {
private CollapsingToolbarLayout mCollapsingToolbarLayout;
- private Toolbar mToolbar;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
@@ -45,8 +44,8 @@
super.setContentView(R.layout.collapsing_toolbar_base_layout);
mCollapsingToolbarLayout = findViewById(R.id.collapsing_toolbar);
- mToolbar = findViewById(R.id.action_bar);
- setActionBar(mToolbar);
+ final Toolbar toolbar = findViewById(R.id.action_bar);
+ setActionBar(toolbar);
// Enable title and home button by default
final ActionBar actionBar = getActionBar();
@@ -97,16 +96,11 @@
@Override
public boolean onNavigateUp() {
if (!super.onNavigateUp()) {
- finish();
+ finishAfterTransition();
}
return true;
}
- @Override
- public Toolbar getToolbar() {
- return mToolbar;
- }
-
/**
* Returns an instance of collapsing toolbar.
*/
diff --git a/packages/SettingsLib/CollapsingToolbarBaseActivity/src/com/android/settingslib/collapsingtoolbar/SettingsTransitionActivity.java b/packages/SettingsLib/CollapsingToolbarBaseActivity/src/com/android/settingslib/collapsingtoolbar/SettingsTransitionActivity.java
index b4fe7ed..4c45c5e 100644
--- a/packages/SettingsLib/CollapsingToolbarBaseActivity/src/com/android/settingslib/collapsingtoolbar/SettingsTransitionActivity.java
+++ b/packages/SettingsLib/CollapsingToolbarBaseActivity/src/com/android/settingslib/collapsingtoolbar/SettingsTransitionActivity.java
@@ -18,14 +18,11 @@
import android.app.ActivityOptions;
import android.content.Intent;
-import android.os.Build;
import android.os.Bundle;
import android.util.Log;
-import android.view.MenuItem;
import android.view.Window;
import android.widget.Toolbar;
-import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.os.BuildCompat;
import androidx.fragment.app.FragmentActivity;
@@ -40,117 +37,85 @@
private static final String TAG = "SettingsTransitionActivity";
private static final int DEFAULT_REQUEST = -1;
+ private Toolbar mToolbar;
+
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
- if (BuildCompat.isAtLeastS()) {
+ if (isSettingsTransitionEnabled()) {
getWindow().requestFeature(Window.FEATURE_ACTIVITY_TRANSITIONS);
SettingsTransitionHelper.applyForwardTransition(this);
SettingsTransitionHelper.applyBackwardTransition(this);
}
+
super.onCreate(savedInstanceState);
}
@Override
- public void startActivity(Intent intent) {
- if (!BuildCompat.isAtLeastS()) {
- super.startActivity(intent);
- return;
- }
- final Toolbar toolbar = getToolbar();
- if (toolbar == null) {
- Log.w(TAG, "Toolbar is null. Cannot apply settings transition!");
- super.startActivity(intent);
- return;
- }
- super.startActivity(intent, getActivityOptionsBundle(toolbar));
+ public void setActionBar(@Nullable Toolbar toolbar) {
+ super.setActionBar(toolbar);
+ mToolbar = toolbar;
+ }
+
+ @Override
+ public void startActivity(Intent intent) {
+ if (!isSettingsTransitionEnabled()) {
+ super.startActivity(intent);
+ return;
+ }
+
+ super.startActivity(intent, createActivityOptionsBundleForTransition(null));
}
@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
- if (!BuildCompat.isAtLeastS()) {
+ if (!isSettingsTransitionEnabled()) {
super.startActivity(intent, options);
return;
}
- final Toolbar toolbar = getToolbar();
- if (toolbar == null) {
- Log.w(TAG, "Toolbar is null. Cannot apply settings transition!");
- super.startActivity(intent, options);
- return;
- }
- if (options != null) {
- super.startActivity(intent, getMergedBundleForTransition(options));
- return;
- }
- super.startActivity(intent, getActivityOptionsBundle(toolbar));
+
+ super.startActivity(intent, createActivityOptionsBundleForTransition(options));
}
@Override
public void startActivityForResult(Intent intent, int requestCode) {
- if (!BuildCompat.isAtLeastS() || requestCode == DEFAULT_REQUEST) {
+ if (!isSettingsTransitionEnabled() || requestCode == DEFAULT_REQUEST) {
super.startActivityForResult(intent, requestCode);
return;
}
- final Toolbar toolbar = getToolbar();
- if (toolbar == null) {
- Log.w(TAG, "Toolbar is null. Cannot apply settings transition!");
- super.startActivityForResult(intent, requestCode);
- return;
- }
- super.startActivityForResult(intent, requestCode, getActivityOptionsBundle(toolbar));
+ super.startActivityForResult(intent, requestCode, createActivityOptionsBundleForTransition(
+ null));
}
@Override
public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
- if (!BuildCompat.isAtLeastS() || requestCode == DEFAULT_REQUEST) {
+ if (!isSettingsTransitionEnabled() || requestCode == DEFAULT_REQUEST) {
super.startActivityForResult(intent, requestCode, options);
return;
}
- final Toolbar toolbar = getToolbar();
- if (toolbar == null) {
- Log.w(TAG, "Toolbar is null. Cannot apply settings transition!");
- super.startActivityForResult(intent, requestCode, options);
- return;
- }
- if (options != null) {
- super.startActivityForResult(intent, requestCode,
- getMergedBundleForTransition(options));
- return;
- }
- super.startActivityForResult(intent, requestCode, getActivityOptionsBundle(toolbar));
+ super.startActivityForResult(intent, requestCode, createActivityOptionsBundleForTransition(
+ options));
}
- @Override
- public boolean onOptionsItemSelected(@NonNull MenuItem item) {
- final int id = item.getItemId();
- if (id == android.R.id.home) {
- // Make the up button behave the same as the back button.
- onBackPressed();
- return true;
- }
- return super.onOptionsItemSelected(item);
+ protected boolean isSettingsTransitionEnabled() {
+ return BuildCompat.isAtLeastS();
}
- /**
- * Subclasses should implement this method and return their {@link Toolbar}.
- */
- public abstract Toolbar getToolbar();
-
- private Bundle getActivityOptionsBundle(Toolbar toolbar) {
- return ActivityOptions.makeSceneTransitionAnimation(this, toolbar,
- "shared_element_view").toBundle();
- }
-
- private Bundle getMergedBundleForTransition(@NonNull Bundle options) {
- final Toolbar toolbar = getToolbar();
- final Bundle mergedBundle = new Bundle();
- mergedBundle.putAll(options);
- final Bundle activityOptionsBundle = getActivityOptionsBundle(toolbar);
- if (activityOptionsBundle != null) {
- mergedBundle.putAll(activityOptionsBundle);
+ @Nullable
+ private Bundle createActivityOptionsBundleForTransition(@Nullable Bundle options) {
+ if (mToolbar == null) {
+ Log.w(TAG, "setActionBar(Toolbar) is not called. Cannot apply settings transition!");
+ return options;
}
- return mergedBundle;
+ final Bundle transitionOptions = ActivityOptions.makeSceneTransitionAnimation(this,
+ mToolbar, "shared_element_view").toBundle();
+ if (options == null) {
+ return transitionOptions;
+ }
+ final Bundle mergedOptions = new Bundle(options);
+ mergedOptions.putAll(transitionOptions);
+ return mergedOptions;
}
}
diff --git a/packages/SettingsLib/FooterPreference/res/layout-v31/preference_footer.xml b/packages/SettingsLib/FooterPreference/res/layout-v31/preference_footer.xml
index 205485d..3b50acc 100644
--- a/packages/SettingsLib/FooterPreference/res/layout-v31/preference_footer.xml
+++ b/packages/SettingsLib/FooterPreference/res/layout-v31/preference_footer.xml
@@ -49,7 +49,6 @@
android:layout_height="wrap_content"
android:paddingBottom="16dp"
android:paddingTop="16dp"
- android:maxLines="10"
android:textColor="?android:attr/textColorSecondary"
android:ellipsize="marquee" />
diff --git a/packages/SettingsLib/FooterPreference/res/layout/preference_footer.xml b/packages/SettingsLib/FooterPreference/res/layout/preference_footer.xml
index 7567c17..87e8358 100644
--- a/packages/SettingsLib/FooterPreference/res/layout/preference_footer.xml
+++ b/packages/SettingsLib/FooterPreference/res/layout/preference_footer.xml
@@ -48,7 +48,6 @@
android:layout_height="wrap_content"
android:paddingBottom="16dp"
android:paddingTop="16dp"
- android:maxLines="10"
android:textColor="?android:attr/textColorSecondary"
android:ellipsize="marquee" />
diff --git a/packages/SettingsLib/IllustrationPreference/res/layout/illustration_preference.xml b/packages/SettingsLib/IllustrationPreference/res/layout/illustration_preference.xml
index 2cbb888..7d65aae 100644
--- a/packages/SettingsLib/IllustrationPreference/res/layout/illustration_preference.xml
+++ b/packages/SettingsLib/IllustrationPreference/res/layout/illustration_preference.xml
@@ -23,20 +23,13 @@
android:gravity="center"
android:orientation="horizontal">
- <View
- android:id="@+id/protection_layer"
- android:layout_width="412dp"
- android:layout_height="300dp"
- android:layout_gravity="center"
- android:padding="@dimen/settingslib_illustration_padding"
- android:background="@drawable/protection_background"/>
-
<com.airbnb.lottie.LottieAnimationView
android:id="@+id/lottie_view"
android:layout_width="412dp"
android:layout_height="300dp"
android:layout_gravity="center"
- android:padding="@dimen/settingslib_illustration_padding"
+ android:clipToOutline="true"
+ android:background="@drawable/protection_background"
android:importantForAccessibility="no"/>
<ImageView
diff --git a/packages/SettingsLib/MainSwitchPreference/res/drawable/settingslib_thumb_disabled.xml b/packages/SettingsLib/MainSwitchPreference/res/drawable/settingslib_thumb_disabled.xml
index 900400e..b41762f 100644
--- a/packages/SettingsLib/MainSwitchPreference/res/drawable/settingslib_thumb_disabled.xml
+++ b/packages/SettingsLib/MainSwitchPreference/res/drawable/settingslib_thumb_disabled.xml
@@ -26,7 +26,7 @@
android:height="@dimen/settingslib_switch_thumb_size"
android:width="@dimen/settingslib_switch_thumb_size"/>
<solid
- android:color="@color/settingslib_state_off_color"
+ android:color="@color/settingslib_thumb_off_color"
android:alpha="?android:attr/disabledAlpha"/>
</shape>
</item>
diff --git a/packages/SettingsLib/MainSwitchPreference/res/drawable/settingslib_thumb_off.xml b/packages/SettingsLib/MainSwitchPreference/res/drawable/settingslib_thumb_off.xml
index e54c332..8b69ad1 100644
--- a/packages/SettingsLib/MainSwitchPreference/res/drawable/settingslib_thumb_off.xml
+++ b/packages/SettingsLib/MainSwitchPreference/res/drawable/settingslib_thumb_off.xml
@@ -25,7 +25,7 @@
<size
android:height="@dimen/settingslib_switch_thumb_size"
android:width="@dimen/settingslib_switch_thumb_size"/>
- <solid android:color="@color/settingslib_state_off_color"/>
+ <solid android:color="@color/settingslib_thumb_off_color"/>
</shape>
</item>
</layer-list>
diff --git a/packages/SettingsLib/MainSwitchPreference/res/layout-v31/settingslib_main_switch_bar.xml b/packages/SettingsLib/MainSwitchPreference/res/layout-v31/settingslib_main_switch_bar.xml
index 27c30ca6..010b9ba 100644
--- a/packages/SettingsLib/MainSwitchPreference/res/layout-v31/settingslib_main_switch_bar.xml
+++ b/packages/SettingsLib/MainSwitchPreference/res/layout-v31/settingslib_main_switch_bar.xml
@@ -19,10 +19,6 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content"
android:layout_width="match_parent"
- android:paddingStart="?android:attr/listPreferredItemPaddingStart"
- android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
- android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"
- android:paddingRight="?android:attr/listPreferredItemPaddingRight"
android:background="?android:attr/colorBackground"
android:orientation="vertical">
@@ -31,15 +27,16 @@
android:minHeight="@dimen/settingslib_min_switch_bar_height"
android:layout_height="wrap_content"
android:layout_width="match_parent"
- android:paddingLeft="@dimen/settingslib_switchbar_margin_start"
- android:paddingRight="@dimen/settingslib_switchbar_margin_end">
+ android:layout_margin="@dimen/settingslib_switchbar_margin"
+ android:paddingStart="@dimen/settingslib_switchbar_padding_left"
+ android:paddingEnd="@dimen/settingslib_switchbar_padding_right">
<TextView
android:id="@+id/switch_text"
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_weight="1"
- android:layout_marginRight="16dp"
+ android:layout_marginEnd="16dp"
android:layout_gravity="center_vertical"
android:maxLines="2"
android:ellipsize="end"
diff --git a/packages/SettingsLib/MainSwitchPreference/res/values-night/colors.xml b/packages/SettingsLib/MainSwitchPreference/res/values-night/colors.xml
index c8d06d4..9ca3683 100644
--- a/packages/SettingsLib/MainSwitchPreference/res/values-night/colors.xml
+++ b/packages/SettingsLib/MainSwitchPreference/res/values-night/colors.xml
@@ -15,10 +15,16 @@
limitations under the License.
-->
-<resources xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
+<resources>
<color name="settingslib_switchbar_switch_track_tint">#82000000</color>
<color name="settingslib_switchbar_switch_thumb_tint">@android:color/black</color>
+ <!-- Material next thumb off color-->
+ <color name="settingslib_thumb_off_color">@android:color/system_neutral2_300</color>
+
<!-- Material next track on color-->
- <color name="settingslib_track_on_color">?androidprv:attr/colorSurfaceHighlight</color>
+ <color name="settingslib_track_on_color">@android:color/system_accent2_700</color>
+
+ <!-- Material next track off color-->
+ <color name="settingslib_track_off_color">@android:color/system_neutral1_700</color>
</resources>
diff --git a/packages/SettingsLib/MainSwitchPreference/res/values/colors.xml b/packages/SettingsLib/MainSwitchPreference/res/values/colors.xml
index 3fcc1dd..2c73238 100644
--- a/packages/SettingsLib/MainSwitchPreference/res/values/colors.xml
+++ b/packages/SettingsLib/MainSwitchPreference/res/values/colors.xml
@@ -26,9 +26,12 @@
<!-- Material next state off color-->
<color name="settingslib_state_off_color">?androidprv:attr/colorAccentSecondary</color>
+ <!-- Material next thumb off color-->
+ <color name="settingslib_thumb_off_color">@android:color/system_neutral2_100</color>
+
<!-- Material next track on color-->
<color name="settingslib_track_on_color">?androidprv:attr/colorAccentPrimaryVariant</color>
<!-- Material next track off color-->
- <color name="settingslib_track_off_color">?androidprv:attr/colorAccentSecondaryVariant</color>
+ <color name="settingslib_track_off_color">@android:color/system_neutral2_600</color>
</resources>
diff --git a/packages/SettingsLib/MainSwitchPreference/res/values/dimens.xml b/packages/SettingsLib/MainSwitchPreference/res/values/dimens.xml
index 4c528da..a1cbcf72 100644
--- a/packages/SettingsLib/MainSwitchPreference/res/values/dimens.xml
+++ b/packages/SettingsLib/MainSwitchPreference/res/values/dimens.xml
@@ -17,11 +17,14 @@
<resources>
+ <!-- Size of layout margin -->
+ <dimen name="settingslib_switchbar_margin">16dp</dimen>
+
<!-- Size of layout margin left -->
- <dimen name="settingslib_switchbar_margin_start">24dp</dimen>
+ <dimen name="settingslib_switchbar_padding_left">24dp</dimen>
<!-- Size of layout margin right -->
- <dimen name="settingslib_switchbar_margin_end">16dp</dimen>
+ <dimen name="settingslib_switchbar_padding_right">16dp</dimen>
<!-- Minimum width of switch -->
<dimen name="settingslib_min_switch_width">52dp</dimen>
diff --git a/packages/SettingsLib/TwoTargetPreference/res/layout/preference_two_target.xml b/packages/SettingsLib/TwoTargetPreference/res/layout/preference_two_target.xml
index f6a64c6..21fcedc 100644
--- a/packages/SettingsLib/TwoTargetPreference/res/layout/preference_two_target.xml
+++ b/packages/SettingsLib/TwoTargetPreference/res/layout/preference_two_target.xml
@@ -23,16 +23,16 @@
android:layout_height="wrap_content"
android:minHeight="?android:attr/listPreferredItemHeightSmall"
android:gravity="center_vertical"
- android:background="?android:attr/selectableItemBackground"
+ android:background="@android:color/transparent"
android:clipToPadding="false">
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
+ android:background="?android:attr/selectableItemBackground"
android:gravity="start|center_vertical"
android:clipToPadding="false"
- android:duplicateParentState="true"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
@@ -44,14 +44,12 @@
android:minWidth="56dp"
android:orientation="horizontal"
android:clipToPadding="false"
- android:duplicateParentState="true"
android:paddingTop="4dp"
android:paddingBottom="4dp">
<androidx.preference.internal.PreferenceImageView
android:id="@android:id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:duplicateParentState="true"
settings:maxWidth="48dp"
settings:maxHeight="48dp" />
</LinearLayout>
@@ -60,7 +58,6 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
- android:duplicateParentState="true"
android:paddingTop="16dp"
android:paddingBottom="16dp">
@@ -69,7 +66,6 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
- android:duplicateParentState="true"
android:textAppearance="?android:attr/textAppearanceListItem"
android:ellipsize="marquee" />
@@ -79,7 +75,6 @@
android:layout_height="wrap_content"
android:layout_below="@android:id/title"
android:layout_alignStart="@android:id/title"
- android:duplicateParentState="true"
android:textAppearance="?android:attr/textAppearanceListItemSecondary"
android:textColor="?android:attr/textColorSecondary"
android:maxLines="10" />
@@ -95,7 +90,6 @@
android:id="@android:id/widget_frame"
android:layout_width="wrap_content"
android:layout_height="match_parent"
- android:duplicateParentState="true"
android:minWidth="64dp"
android:gravity="center"
android:orientation="vertical" />
diff --git a/packages/SettingsLib/TwoTargetPreference/res/layout/preference_two_target_divider.xml b/packages/SettingsLib/TwoTargetPreference/res/layout/preference_two_target_divider.xml
index 44732e5..bd477f8 100644
--- a/packages/SettingsLib/TwoTargetPreference/res/layout/preference_two_target_divider.xml
+++ b/packages/SettingsLib/TwoTargetPreference/res/layout/preference_two_target_divider.xml
@@ -22,12 +22,10 @@
android:layout_height="match_parent"
android:gravity="start|center_vertical"
android:orientation="horizontal"
- android:duplicateParentState="true"
android:paddingTop="16dp"
android:paddingBottom="16dp">
<View
android:layout_width="1dp"
android:layout_height="match_parent"
- android:duplicateParentState="true"
android:background="?android:attr/listDivider" />
</LinearLayout>
\ No newline at end of file
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index f3bd92b..8e7bbaa 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -460,8 +460,7 @@
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Laai tans stadig"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Laai tans draadloos"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Laai nie"</string>
- <!-- no translation found for battery_info_status_not_charging (3371084153747234837) -->
- <skip />
+ <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Gekoppel, laai nie"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Gelaai"</string>
<string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Beheer deur administrateur"</string>
<string name="disabled" msgid="8017887509554714950">"Gedeaktiveer"</string>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index 6e96887..4e30f38 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -460,8 +460,7 @@
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"جارٍ الشحن ببطء"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"جارٍ الشحن لاسلكيًا"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"لا يتم الشحن"</string>
- <!-- no translation found for battery_info_status_not_charging (3371084153747234837) -->
- <skip />
+ <string name="battery_info_status_not_charging" msgid="3371084153747234837">"الجهاز متصل بالشاحن، ولا يتم الشحن."</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"تم الشحن"</string>
<string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"إعدادات يتحكم فيها المشرف"</string>
<string name="disabled" msgid="8017887509554714950">"غير مفعّل"</string>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index 38f6b69..cc00047 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -460,8 +460,7 @@
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"লাহে লাহে চাৰ্জ হৈছে"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"বেতাঁৰৰ মাধ্যমেৰে চাৰ্জ হৈ আছে"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"চ্চাৰ্জ কৰা নাই"</string>
- <!-- no translation found for battery_info_status_not_charging (3371084153747234837) -->
- <skip />
+ <string name="battery_info_status_not_charging" msgid="3371084153747234837">"সংযোগ হৈ আছে, চাৰ্জ হৈ থকা নাই"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"চাৰ্জ হ’ল"</string>
<string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"এডমিনৰ দ্বাৰা নিয়ন্ত্ৰিত"</string>
<string name="disabled" msgid="8017887509554714950">"নিষ্ক্ৰিয়"</string>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index 75fa059..41d4b6e 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -460,8 +460,7 @@
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Asta doldurulur"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Simsiz şarj edilir"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Doldurulmur"</string>
- <!-- no translation found for battery_info_status_not_charging (3371084153747234837) -->
- <skip />
+ <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Qoşulub, şarj edilmir"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Şarj edilib"</string>
<string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Admin tərəfindən nəzarət olunur"</string>
<string name="disabled" msgid="8017887509554714950">"Deaktiv"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 2308830..b056e30 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -460,8 +460,7 @@
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Sporo se puni"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Bežično punjenje"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Ne puni se"</string>
- <!-- no translation found for battery_info_status_not_charging (3371084153747234837) -->
- <skip />
+ <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Povezano, ne puni se"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Napunjeno"</string>
<string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Kontroliše administrator"</string>
<string name="disabled" msgid="8017887509554714950">"Onemogućeno"</string>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 59a54c8..59d63c5 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -460,8 +460,7 @@
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Павольная зарадка"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Бесправадная зарадка"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Не зараджаецца"</string>
- <!-- no translation found for battery_info_status_not_charging (3371084153747234837) -->
- <skip />
+ <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Падключана, не зараджаецца"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Зараджаны"</string>
<string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Кантралюецца адміністратарам"</string>
<string name="disabled" msgid="8017887509554714950">"Адключанае"</string>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index 19664aa..7db27d2 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -460,8 +460,7 @@
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"ধীরে চার্জ হচ্ছে"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"কেবল ছাড়া চার্জ হচ্ছে"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"চার্জ হচ্ছে না"</string>
- <!-- no translation found for battery_info_status_not_charging (3371084153747234837) -->
- <skip />
+ <string name="battery_info_status_not_charging" msgid="3371084153747234837">"কানেক্ট করা থাকলেও চার্জ করা হচ্ছে না"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"চার্জ হয়েছে"</string>
<string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"প্রশাসকের দ্বারা নিয়ন্ত্রিত"</string>
<string name="disabled" msgid="8017887509554714950">"অক্ষম হয়েছে"</string>
@@ -507,9 +506,9 @@
<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" 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="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-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 1b63b9a..4e57750 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -460,8 +460,7 @@
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Pomalé nabíjení"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Bezdrátové nabíjení"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Nenabíjí se"</string>
- <!-- no translation found for battery_info_status_not_charging (3371084153747234837) -->
- <skip />
+ <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Připojeno, nenabíjí se"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Nabito"</string>
<string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Spravováno administrátorem"</string>
<string name="disabled" msgid="8017887509554714950">"Deaktivováno"</string>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index a5ae7d1..fc96cbf 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -460,8 +460,7 @@
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Oplader langsomt"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Trådløs opladning"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Oplader ikke"</string>
- <!-- no translation found for battery_info_status_not_charging (3371084153747234837) -->
- <skip />
+ <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Tilsluttet, oplader ikke"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Opladet"</string>
<string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Kontrolleret af administratoren"</string>
<string name="disabled" msgid="8017887509554714950">"Deaktiveret"</string>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index ff68b13..b5b579e 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -506,9 +506,9 @@
<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. Du kannst diese App nutzen, wenn du dein Smartphone 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. Du kannst diese App nutzen, wenn du dein Tablet 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. Du kannst diese App nutzen, wenn du dein 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="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>
<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 6136def..cb76522 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -460,8 +460,7 @@
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Αργή φόρτιση"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Ασύρματη φόρτιση"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Δεν φορτίζει"</string>
- <!-- no translation found for battery_info_status_not_charging (3371084153747234837) -->
- <skip />
+ <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Συνδεδεμένη, δεν φορτίζει"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Φορτισμένη"</string>
<string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Ελέγχονται από το διαχειριστή"</string>
<string name="disabled" msgid="8017887509554714950">"Απενεργοποιημένο"</string>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index 6dce3e2..d46a99b 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -460,8 +460,7 @@
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Aeglaselt laadimine"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Juhtmevaba laadimine"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Ei lae"</string>
- <!-- no translation found for battery_info_status_not_charging (3371084153747234837) -->
- <skip />
+ <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Ühendatud, ei laeta"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Laetud"</string>
<string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Juhib administraator"</string>
<string name="disabled" msgid="8017887509554714950">"Keelatud"</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index f8692a07..7eae947 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -460,8 +460,7 @@
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"درحال شارژ شدن آهسته"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"درحال شارژ بیسیم"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"شارژ نمیشود"</string>
- <!-- no translation found for battery_info_status_not_charging (3371084153747234837) -->
- <skip />
+ <string name="battery_info_status_not_charging" msgid="3371084153747234837">"متصل، شارژ نمیشود"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"شارژ کامل شد"</string>
<string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"توسط سرپرست سیستم کنترل میشود"</string>
<string name="disabled" msgid="8017887509554714950">"غیر فعال شد"</string>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 371fc57..af97b8d 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -460,8 +460,7 @@
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Hidas lataus"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Langaton lataus"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Ei laturissa"</string>
- <!-- no translation found for battery_info_status_not_charging (3371084153747234837) -->
- <skip />
+ <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Yhdistetty, ei ladata"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Ladattu"</string>
<string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Järjestelmänvalvoja hallinnoi tätä asetusta."</string>
<string name="disabled" msgid="8017887509554714950">"Pois päältä"</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index 8e22f81..36bdf47 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -197,10 +197,10 @@
<string name="choose_profile" msgid="343803890897657450">"Sélectionnez un profil"</string>
<string name="category_personal" msgid="6236798763159385225">"Personnel"</string>
<string name="category_work" msgid="4014193632325996115">"Professionnel"</string>
- <string name="development_settings_title" msgid="140296922921597393">"Options pour les concepteurs"</string>
- <string name="development_settings_enable" msgid="4285094651288242183">"Activer les options pour les concepteurs"</string>
+ <string name="development_settings_title" msgid="140296922921597393">"Options pour les développeurs"</string>
+ <string name="development_settings_enable" msgid="4285094651288242183">"Activer les options pour les développeurs"</string>
<string name="development_settings_summary" msgid="8718917813868735095">"Définir les options pour le développement de l\'application"</string>
- <string name="development_settings_not_available" msgid="355070198089140951">"Les options proposées aux concepteurs ne sont pas disponibles pour cet utilisateur."</string>
+ <string name="development_settings_not_available" msgid="355070198089140951">"Les options proposées aux développeurs ne sont pas disponibles pour cet utilisateur."</string>
<string name="vpn_settings_not_available" msgid="2894137119965668920">"Les paramètres de RPV ne sont pas disponibles pour cet utilisateur"</string>
<string name="tethering_settings_not_available" msgid="266821736434699780">"Les paramètres de partage de connexion ne sont pas disponibles pour cet utilisateur"</string>
<string name="apn_settings_not_available" msgid="1147111671403342300">"Les paramètres de point d\'accès ne sont pas disponibles pour cet utilisateur"</string>
@@ -234,7 +234,7 @@
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Numériser le code QR"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="6014121407143607851">"Associer l\'appareil par Wi-Fi en numérisant un code QR"</string>
<string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Veuillez vous connecter à un réseau Wi-Fi"</string>
- <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, débogage, concepteur"</string>
+ <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, débogage, développeur"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Raccourci de rapport de bogue"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Afficher un bouton permettant d\'établir un rapport de bogue dans le menu de démarrage"</string>
<string name="keep_screen_on" msgid="1187161672348797558">"Rester activé"</string>
@@ -562,7 +562,7 @@
<string name="user_need_lock_message" msgid="4311424336209509301">"Avant de créer un profil limité, vous devez définir un écran de verrouillage pour protéger vos applications et vos données personnelles."</string>
<string name="user_set_lock_button" msgid="1427128184982594856">"Définir verrouillage écran"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Passer à <xliff:g id="USER_NAME">%s</xliff:g>"</string>
- <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Création d\'un utilisateur..."</string>
+ <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Création d\'un utilisateur en cours…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Impossible de créer un utilisateur"</string>
<string name="user_nickname" msgid="262624187455825083">"Pseudo"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Ajouter un invité"</string>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 2556608..0645b9e 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -460,8 +460,7 @@
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Charge lente"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"En charge sans fil"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Pas en charge"</string>
- <!-- no translation found for battery_info_status_not_charging (3371084153747234837) -->
- <skip />
+ <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Connecté, pas en charge"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Chargée"</string>
<string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Contrôlé par l\'administrateur"</string>
<string name="disabled" msgid="8017887509554714950">"Désactivée"</string>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index d6daeb0..8425e62 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -460,8 +460,7 @@
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Cargando lentamente"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Cargando sen fíos"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Non se está cargando"</string>
- <!-- no translation found for battery_info_status_not_charging (3371084153747234837) -->
- <skip />
+ <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Conectado, sen cargar"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Cargada"</string>
<string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Opción controlada polo administrador"</string>
<string name="disabled" msgid="8017887509554714950">"Desactivada"</string>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index ebfd7c5..7fa52f5 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -460,8 +460,7 @@
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"ધીમેથી ચાર્જ થાય છે"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"વાયરલેસથી ચાર્જિંગ"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"ચાર્જ થઈ રહ્યું નથી"</string>
- <!-- no translation found for battery_info_status_not_charging (3371084153747234837) -->
- <skip />
+ <string name="battery_info_status_not_charging" msgid="3371084153747234837">"કનેક્ટ કરેલું છે, પણ ચાર્જ થઈ રહ્યું નથી"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"ચાર્જ થયું"</string>
<string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"વ્યવસ્થાપક દ્વારા નિયંત્રિત"</string>
<string name="disabled" msgid="8017887509554714950">"અક્ષમ કર્યો"</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 6d45dae..88ab593 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -460,8 +460,7 @@
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"धीरे चार्ज हो रही है"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"वायरलेस चार्जिंग"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"चार्ज नहीं हो रही है"</string>
- <!-- no translation found for battery_info_status_not_charging (3371084153747234837) -->
- <skip />
+ <string name="battery_info_status_not_charging" msgid="3371084153747234837">"कनेक्ट किया गया, चार्ज नहीं हो रहा है"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"बैटरी चार्ज हो गई"</string>
<string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"इसका नियंत्रण एडमिन के पास है"</string>
<string name="disabled" msgid="8017887509554714950">"बंद किया गया"</string>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index d56a848..4adef4d 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -460,8 +460,7 @@
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Lassú töltés"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Vezeték nélküli töltés"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Nem tölt"</string>
- <!-- no translation found for battery_info_status_not_charging (3371084153747234837) -->
- <skip />
+ <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Csatlakoztatva, nem töltődik"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Feltöltve"</string>
<string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Rendszergazda által irányítva"</string>
<string name="disabled" msgid="8017887509554714950">"Letiltva"</string>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index 5256824..8abfdec 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -460,8 +460,7 @@
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Դանդաղ լիցքավորում"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Անլար լիցքավորում"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Չի լիցքավորվում"</string>
- <!-- no translation found for battery_info_status_not_charging (3371084153747234837) -->
- <skip />
+ <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Միացված է, չի լիցքավորվում"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Լիցքավորված է"</string>
<string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Վերահսկվում է ադմինիստրատորի կողմից"</string>
<string name="disabled" msgid="8017887509554714950">"Կասեցված է"</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 7ef23dc..85f6999 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -506,7 +506,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. Utilizzare quest\'app quando non stai usando il tuo telefono 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="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="keywords_alarms_and_reminders" msgid="6633360095891110611">"programmare, sveglia, promemoria, orologio"</string>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index e8c95c3..f3a533f 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -460,8 +460,7 @@
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Баяу зарядталуда"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Сымсыз зарядталуда"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Зарядталу орындалып жатқан жоқ"</string>
- <!-- no translation found for battery_info_status_not_charging (3371084153747234837) -->
- <skip />
+ <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Жалғанған, зарядталып жатқан жоқ"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Зарядталды"</string>
<string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Әкімші басқарады"</string>
<string name="disabled" msgid="8017887509554714950">"Өшірілген"</string>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index a069ec4..3a5199f 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -460,8 +460,7 @@
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"កំពុងសាកថ្មយឺត"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"កំពុងសាកថ្មឥតខ្សែ"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"មិនកំពុងបញ្ចូលថ្ម"</string>
- <!-- no translation found for battery_info_status_not_charging (3371084153747234837) -->
- <skip />
+ <string name="battery_info_status_not_charging" msgid="3371084153747234837">"បានភ្ជាប់ មិនកំពុងសាកថ្ម"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"បានសាកថ្ម"</string>
<string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"គ្រប់គ្រងដោយអ្នកគ្រប់គ្រង"</string>
<string name="disabled" msgid="8017887509554714950">"បិទ"</string>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index 44e4e8e..e886de5 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -460,8 +460,7 @@
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"ನಿಧಾನ ಗತಿಯ ಚಾರ್ಜಿಂಗ್"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"ವೈರ್ಲೆಸ್ ಚಾರ್ಜಿಂಗ್"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"ಚಾರ್ಜ್ ಆಗುತ್ತಿಲ್ಲ"</string>
- <!-- no translation found for battery_info_status_not_charging (3371084153747234837) -->
- <skip />
+ <string name="battery_info_status_not_charging" msgid="3371084153747234837">"ಕನೆಕ್ಟ್ ಆಗಿದೆ, ಚಾರ್ಜ್ ಆಗುತ್ತಿಲ್ಲ"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"ಚಾರ್ಜ್ ಆಗಿದೆ"</string>
<string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"ನಿರ್ವಾಹಕರ ಮೂಲಕ ನಿಯಂತ್ರಿಸಲಾಗಿದೆ"</string>
<string name="disabled" msgid="8017887509554714950">"ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index d449a7f..918250c 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -460,8 +460,7 @@
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"저속 충전 중"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"무선 충전 중"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"충전 안함"</string>
- <!-- no translation found for battery_info_status_not_charging (3371084153747234837) -->
- <skip />
+ <string name="battery_info_status_not_charging" msgid="3371084153747234837">"연결됨, 충전 중 아님"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"청구됨"</string>
<string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"관리자가 제어"</string>
<string name="disabled" msgid="8017887509554714950">"사용 안함"</string>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 10c3526..8efc1e4 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -460,8 +460,7 @@
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Жай кубатталууда"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Зымсыз кубатталууда"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Кубат алган жок"</string>
- <!-- no translation found for battery_info_status_not_charging (3371084153747234837) -->
- <skip />
+ <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Туташты, кубатталган жок"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Кубатталды"</string>
<string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Администратор тарабынан көзөмөлдөнөт"</string>
<string name="disabled" msgid="8017887509554714950">"Өчүрүлгөн"</string>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index b9fcec1..77a5d4b 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -460,8 +460,7 @@
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Notiek lēnā uzlāde"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Bezvadu uzlāde"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Nenotiek uzlāde"</string>
- <!-- no translation found for battery_info_status_not_charging (3371084153747234837) -->
- <skip />
+ <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Ierīce pievienota, uzlāde nenotiek"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Uzlādēts"</string>
<string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Kontrolē administrators"</string>
<string name="disabled" msgid="8017887509554714950">"Atspējots"</string>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index a31c344..11c160d 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -460,8 +460,7 @@
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"പതുക്കെയുള്ള ചാർജിംഗ്"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"വയർലെസായി ചാർജുചെയ്യുന്നു"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"ചാർജ്ജുചെയ്യുന്നില്ല"</string>
- <!-- no translation found for battery_info_status_not_charging (3371084153747234837) -->
- <skip />
+ <string name="battery_info_status_not_charging" msgid="3371084153747234837">"കണക്റ്റ് ചെയ്തിരിക്കുന്നു, ചാർജ് ചെയ്യുന്നില്ല"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"ചാർജായി"</string>
<string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"അഡ്മിൻ നിയന്ത്രിക്കുന്നത്"</string>
<string name="disabled" msgid="8017887509554714950">"പ്രവർത്തനരഹിതമാക്കി"</string>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index 23ebd39..16c7f39 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -460,8 +460,7 @@
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"हळूहळू चार्ज होत आहे"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"वायरलेसने चार्ज होत आहे"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"चार्ज होत नाही"</string>
- <!-- no translation found for battery_info_status_not_charging (3371084153747234837) -->
- <skip />
+ <string name="battery_info_status_not_charging" msgid="3371084153747234837">"कनेक्ट केले, चार्ज होत नाही"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"चार्ज झाली"</string>
<string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"प्रशासकाने नियंत्रित केलेले"</string>
<string name="disabled" msgid="8017887509554714950">"अक्षम"</string>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index 24a1955..9707c5e 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -460,8 +460,7 @@
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Mengecas dgn prlahan"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Mengecas tanpa wayar"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Tidak mengecas"</string>
- <!-- no translation found for battery_info_status_not_charging (3371084153747234837) -->
- <skip />
+ <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Bersambung, tidak mengecas"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Sudah dicas"</string>
<string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Dikawal oleh pentadbir"</string>
<string name="disabled" msgid="8017887509554714950">"Dilumpuhkan"</string>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 41debb6..fa1837f 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -460,8 +460,7 @@
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Lader sakte"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Lader trådløst"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Lader ikke"</string>
- <!-- no translation found for battery_info_status_not_charging (3371084153747234837) -->
- <skip />
+ <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Tilkoblet, lader ikke"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Ladet"</string>
<string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Kontrollert av administratoren"</string>
<string name="disabled" msgid="8017887509554714950">"Slått av"</string>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index 50a09cf..e5e9a96 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -460,8 +460,7 @@
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"बिस्तारै चार्ज गरिँदै"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"वायरलेस तरिकाले चार्ज गरिँदै छ"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"चार्ज भइरहेको छैन"</string>
- <!-- no translation found for battery_info_status_not_charging (3371084153747234837) -->
- <skip />
+ <string name="battery_info_status_not_charging" msgid="3371084153747234837">"कनेक्ट गरिएको छ, चार्ज भइरहेको छैन"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"चार्ज भयो"</string>
<string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"प्रशासकद्वारा नियन्त्रित"</string>
<string name="disabled" msgid="8017887509554714950">"असक्षम पारियो"</string>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index 4ce6dc4..53855a8 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -460,8 +460,7 @@
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"ਹੌਲੀ ਚਾਰਜ ਹੋ ਰਹੀ ਹੈ"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"ਬਿਨਾਂ ਤਾਰ ਤੋਂ ਚਾਰਜ ਹੋ ਰਹੀ ਹੈ"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"ਚਾਰਜ ਨਹੀਂ ਹੋ ਰਿਹਾ"</string>
- <!-- no translation found for battery_info_status_not_charging (3371084153747234837) -->
- <skip />
+ <string name="battery_info_status_not_charging" msgid="3371084153747234837">"ਕਨੈਕਟ ਹੈ, ਚਾਰਜ ਨਹੀਂ ਹੋ ਰਿਹਾ"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"ਚਾਰਜ ਹੋ ਗਈ"</string>
<string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"ਪ੍ਰਸ਼ਾਸਕ ਵੱਲੋਂ ਕੰਟਰੋਲ ਕੀਤੀ ਗਈ"</string>
<string name="disabled" msgid="8017887509554714950">"ਅਯੋਗ ਬਣਾਇਆ"</string>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 6099cd5..ed0b470 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -460,8 +460,7 @@
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Se încarcă lent"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Se încarcă wireless"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Nu se încarcă"</string>
- <!-- no translation found for battery_info_status_not_charging (3371084153747234837) -->
- <skip />
+ <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Conectat, nu se încarcă"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Încărcată"</string>
<string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Controlată de administrator"</string>
<string name="disabled" msgid="8017887509554714950">"Dezactivată"</string>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index 0c73fda..16cb85a 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -460,8 +460,7 @@
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"සෙමින් ආරෝපණය"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"නොරැහැන්ව ආරෝපණය වේ"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"ආරෝපණය නොවේ"</string>
- <!-- no translation found for battery_info_status_not_charging (3371084153747234837) -->
- <skip />
+ <string name="battery_info_status_not_charging" msgid="3371084153747234837">"සම්බන්ධයි, ආරෝපණය නොවේ"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"අරෝපිතයි"</string>
<string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"පරිපාලක විසින් පාලනය කරන ලදී"</string>
<string name="disabled" msgid="8017887509554714950">"අබල කර ඇත"</string>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index ebcbfb9..5e7022d 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -460,8 +460,7 @@
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Споро се пуни"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Бежично пуњење"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Не пуни се"</string>
- <!-- no translation found for battery_info_status_not_charging (3371084153747234837) -->
- <skip />
+ <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Повезано, не пуни се"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Напуњено"</string>
<string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Контролише администратор"</string>
<string name="disabled" msgid="8017887509554714950">"Онемогућено"</string>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 028eb3f..29c6a4f 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -460,8 +460,7 @@
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Inachaji pole pole"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Inachaji bila kutumia waya"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Haichaji"</string>
- <!-- no translation found for battery_info_status_not_charging (3371084153747234837) -->
- <skip />
+ <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Imeunganishwa, haichaji"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Imechajiwa"</string>
<string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Imedhibitiwa na msimamizi"</string>
<string name="disabled" msgid="8017887509554714950">"Imezimwa"</string>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index 155c688..2ac3830 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -460,8 +460,7 @@
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"மெதுவாக சார்ஜாகிறது"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"வயரின்றி சார்ஜாகிறது"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"சார்ஜ் செய்யப்படவில்லை"</string>
- <!-- no translation found for battery_info_status_not_charging (3371084153747234837) -->
- <skip />
+ <string name="battery_info_status_not_charging" msgid="3371084153747234837">"இணைக்கப்பட்டுள்ளது, சார்ஜாகவில்லை"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"சார்ஜாகிவிட்டது"</string>
<string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"நிர்வாகி கட்டுப்படுத்துகிறார்"</string>
<string name="disabled" msgid="8017887509554714950">"முடக்கப்பட்டது"</string>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index c53be38..2cd1bec 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -460,8 +460,7 @@
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"నెమ్మదిగా ఛార్జింగ్"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"వైర్లెస్ ఛార్జింగ్"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"ఛార్జ్ కావడం లేదు"</string>
- <!-- no translation found for battery_info_status_not_charging (3371084153747234837) -->
- <skip />
+ <string name="battery_info_status_not_charging" msgid="3371084153747234837">"కనెక్ట్ చేయబడింది, ఛార్జ్ చేయబడలేదు"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"ఛార్జ్ చేయబడింది"</string>
<string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"నిర్వాహకుని ద్వారా నియంత్రించబడింది"</string>
<string name="disabled" msgid="8017887509554714950">"డిజేబుల్ చేయబడింది"</string>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 52dd165..7f26fc5 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -460,8 +460,7 @@
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"กำลังชาร์จอย่างช้าๆ"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"กำลังชาร์จแบบไร้สาย"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"ไม่ได้ชาร์จ"</string>
- <!-- no translation found for battery_info_status_not_charging (3371084153747234837) -->
- <skip />
+ <string name="battery_info_status_not_charging" msgid="3371084153747234837">"เชื่อมต่ออยู่ ไม่ได้ชาร์จ"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"ชาร์จแล้ว"</string>
<string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"ผู้ดูแลระบบเป็นผู้ควบคุม"</string>
<string name="disabled" msgid="8017887509554714950">"ปิดอยู่"</string>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index a71a958..90b3e7d 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -460,8 +460,7 @@
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"آہستہ چارج ہو رہا ہے"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"وائرلیس طریقے سے چارج ہو رہی ہے"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"چارج نہیں ہو رہا ہے"</string>
- <!-- no translation found for battery_info_status_not_charging (3371084153747234837) -->
- <skip />
+ <string name="battery_info_status_not_charging" msgid="3371084153747234837">"منسلک ہے، چارج نہیں ہو رہی ہے"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"چارج ہو گئی"</string>
<string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"کنٹرول کردہ بذریعہ منتظم"</string>
<string name="disabled" msgid="8017887509554714950">"غیر فعال"</string>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 186aa05..d0c0fa2 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -460,8 +460,7 @@
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Đang sạc chậm"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Đang sạc không dây"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Hiện không sạc"</string>
- <!-- no translation found for battery_info_status_not_charging (3371084153747234837) -->
- <skip />
+ <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Đã kết nối nhưng chưa sạc"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"Đã sạc"</string>
<string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Do quản trị viên kiểm soát"</string>
<string name="disabled" msgid="8017887509554714950">"Đã tắt"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 0069517..da62ded 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -460,8 +460,7 @@
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"正在慢速充电"</string>
<string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"正在无线充电"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"未在充电"</string>
- <!-- no translation found for battery_info_status_not_charging (3371084153747234837) -->
- <skip />
+ <string name="battery_info_status_not_charging" msgid="3371084153747234837">"已连接,尚未充电"</string>
<string name="battery_info_status_full" msgid="1339002294876531312">"已充满电"</string>
<string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"由管理员控制"</string>
<string name="disabled" msgid="8017887509554714950">"已停用"</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/enterprise/ActionDisabledByAdminController.java b/packages/SettingsLib/src/com/android/settingslib/enterprise/ActionDisabledByAdminController.java
new file mode 100644
index 0000000..8730af1
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/enterprise/ActionDisabledByAdminController.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.settingslib.enterprise;
+
+import android.app.Activity;
+import android.content.Context;
+
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AlertDialog.Builder;
+
+import com.android.settingslib.RestrictedLockUtils;
+
+/**
+ * A controller used to customize the action disabled by admin dialog.
+ */
+public interface ActionDisabledByAdminController {
+
+ /**
+ * Handles the adding and setting up of the learn more button. If button is not needed, then
+ * this method can be left empty.
+ */
+ void setupLearnMoreButton(Activity activity, Builder builder);
+
+ /**
+ * Returns the admin support dialog's title resource id.
+ */
+ String getAdminSupportTitle(@Nullable String restriction);
+
+ /**
+ * Returns the admin support dialog's content string.
+ */
+ CharSequence getAdminSupportContentString(
+ Context context, @Nullable CharSequence supportMessage);
+
+ /**
+ * Updates the enforced admin
+ */
+ void updateEnforcedAdmin(RestrictedLockUtils.EnforcedAdmin admin, int adminUserId);
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/enterprise/ActionDisabledByAdminControllerFactory.java b/packages/SettingsLib/src/com/android/settingslib/enterprise/ActionDisabledByAdminControllerFactory.java
new file mode 100644
index 0000000..7eecd19
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/enterprise/ActionDisabledByAdminControllerFactory.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.enterprise;
+
+import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_FINANCED;
+
+import android.app.admin.DevicePolicyManager;
+
+/**
+ * A factory that returns the relevant instance of {@link ActionDisabledByAdminController}.
+ */
+public class ActionDisabledByAdminControllerFactory {
+
+ /**
+ * Returns the relevant instance of {@link ActionDisabledByAdminController}.
+ */
+ public static ActionDisabledByAdminController createInstance(
+ DevicePolicyManager dpm,
+ ActionDisabledLearnMoreButtonLauncher helper,
+ DeviceAdminStringProvider deviceAdminStringProvider) {
+ if (isFinancedDevice(dpm)) {
+ return new FinancedDeviceActionDisabledByAdminController(
+ helper, deviceAdminStringProvider);
+ }
+ return new ManagedDeviceActionDisabledByAdminController(
+ helper, deviceAdminStringProvider);
+ }
+
+ private static boolean isFinancedDevice(DevicePolicyManager dpm) {
+ return dpm.isDeviceManaged() && dpm.getDeviceOwnerType(
+ dpm.getDeviceOwnerComponentOnAnyUser()) == DEVICE_OWNER_TYPE_FINANCED;
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/enterprise/ActionDisabledLearnMoreButtonLauncher.java b/packages/SettingsLib/src/com/android/settingslib/enterprise/ActionDisabledLearnMoreButtonLauncher.java
new file mode 100644
index 0000000..9d2df23
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/enterprise/ActionDisabledLearnMoreButtonLauncher.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.enterprise;
+
+import android.app.Activity;
+
+import androidx.appcompat.app.AlertDialog;
+
+import com.android.settingslib.RestrictedLockUtils;
+
+/**
+ * Helper interface meant to set up the "Learn more" button in the action disabled dialog.
+ */
+public interface ActionDisabledLearnMoreButtonLauncher {
+
+ /**
+ * Sets up a "learn more" button which shows a screen with device policy settings
+ */
+ void setupLearnMoreButtonToShowAdminPolicies(
+ Activity activity,
+ AlertDialog.Builder builder,
+ int enforcementAdminUserId,
+ RestrictedLockUtils.EnforcedAdmin enforcedAdmin);
+
+ /**
+ * Sets up a "learn more" button which launches a help page
+ */
+ void setupLearnMoreButtonToLaunchHelpPage(
+ Activity activity,
+ AlertDialog.Builder builder,
+ String url);
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/enterprise/DeviceAdminStringProvider.java b/packages/SettingsLib/src/com/android/settingslib/enterprise/DeviceAdminStringProvider.java
new file mode 100644
index 0000000..c47d789
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/enterprise/DeviceAdminStringProvider.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.enterprise;
+
+/**
+ * A {@code String} provider for the action disabled by admin dialog.
+ */
+public interface DeviceAdminStringProvider {
+
+ /**
+ * Returns the default dialog title for the case when an action is disabled by policy on a
+ * managed device.
+ */
+ String getDefaultDisabledByPolicyTitle();
+
+ /**
+ * Returns the dialog title for the case when volume adjusting is disabled.
+ */
+ String getDisallowAdjustVolumeTitle();
+
+ /**
+ * Returns the dialog title for the case when outgoing calls are disabled.
+ */
+ String getDisallowOutgoingCallsTitle();
+
+ /**
+ * Returns the dialog title for the case when sending SMS is disabled.
+ */
+ String getDisallowSmsTitle();
+
+ /**
+ * Returns the dialog title for the case when the camera is disabled.
+ */
+ String getDisableCameraTitle();
+
+ /**
+ * Returns the dialog title for the case when screen capturing is disabled.
+ */
+ String getDisableScreenCaptureTitle();
+
+ /**
+ * Returns the dialog title for the case when suspending apps is disabled.
+ */
+ String getSuspendPackagesTitle();
+
+ /**
+ * Returns the default dialog content for the case when an action is disabled by policy.
+ */
+ String getDefaultDisabledByPolicyContent();
+
+ /**
+ * Returns the URL for the page to be shown when the learn more button is chosen.
+ */
+ String getLearnMoreHelpPageUrl();
+
+ /**
+ * Returns the default dialog title for the case when an action is disabled by policy on
+ * a financed device.
+ */
+ String getDisabledByPolicyTitleForFinancedDevice();
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/enterprise/FinancedDeviceActionDisabledByAdminController.java b/packages/SettingsLib/src/com/android/settingslib/enterprise/FinancedDeviceActionDisabledByAdminController.java
new file mode 100644
index 0000000..587979d
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/enterprise/FinancedDeviceActionDisabledByAdminController.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.enterprise;
+
+import static java.util.Objects.requireNonNull;
+
+import android.annotation.UserIdInt;
+import android.app.Activity;
+import android.content.Context;
+
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AlertDialog.Builder;
+
+import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+
+/**
+ * An {@link ActionDisabledByAdminController} to be used with financed devices.
+ */
+public class FinancedDeviceActionDisabledByAdminController
+ implements ActionDisabledByAdminController {
+
+ private @UserIdInt int mEnforcementAdminUserId;
+ private EnforcedAdmin mEnforcedAdmin;
+ private final ActionDisabledLearnMoreButtonLauncher mHelper;
+ private final DeviceAdminStringProvider mDeviceAdminStringProvider;
+
+ FinancedDeviceActionDisabledByAdminController(
+ ActionDisabledLearnMoreButtonLauncher helper,
+ DeviceAdminStringProvider deviceAdminStringProvider) {
+ mHelper = requireNonNull(helper);
+ mDeviceAdminStringProvider = requireNonNull(deviceAdminStringProvider);
+ }
+
+ @Override
+ public void updateEnforcedAdmin(EnforcedAdmin admin, int adminUserId) {
+ mEnforcementAdminUserId = adminUserId;
+ mEnforcedAdmin = requireNonNull(admin);
+ }
+
+ @Override
+ public void setupLearnMoreButton(Activity activity, Builder builder) {
+ mHelper.setupLearnMoreButtonToShowAdminPolicies(
+ activity,
+ builder,
+ mEnforcementAdminUserId,
+ mEnforcedAdmin);
+ }
+
+ @Override
+ public String getAdminSupportTitle(@Nullable String restriction) {
+ return mDeviceAdminStringProvider.getDisabledByPolicyTitleForFinancedDevice();
+ }
+
+ @Override
+ public CharSequence getAdminSupportContentString(Context context, CharSequence supportMessage) {
+ return supportMessage;
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/enterprise/ManagedDeviceActionDisabledByAdminController.java b/packages/SettingsLib/src/com/android/settingslib/enterprise/ManagedDeviceActionDisabledByAdminController.java
new file mode 100644
index 0000000..624c88e
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/enterprise/ManagedDeviceActionDisabledByAdminController.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.enterprise;
+
+import static java.util.Objects.requireNonNull;
+
+import android.annotation.UserIdInt;
+import android.app.Activity;
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.os.UserManager;
+import android.text.TextUtils;
+
+import androidx.appcompat.app.AlertDialog.Builder;
+
+import com.android.settingslib.RestrictedLockUtils;
+
+/**
+ * An {@link ActionDisabledByAdminController} to be used with managed devices.
+ */
+class ManagedDeviceActionDisabledByAdminController implements
+ ActionDisabledByAdminController {
+ private @UserIdInt int mEnforcementAdminUserId;
+ private RestrictedLockUtils.EnforcedAdmin mEnforcedAdmin;
+ private final ActionDisabledLearnMoreButtonLauncher mHelper;
+ private final DeviceAdminStringProvider mStringProvider;
+
+ ManagedDeviceActionDisabledByAdminController(
+ ActionDisabledLearnMoreButtonLauncher helper,
+ DeviceAdminStringProvider stringProvider) {
+ mHelper = requireNonNull(helper);
+ mStringProvider = requireNonNull(stringProvider);
+ }
+
+ @Override
+ public void updateEnforcedAdmin(RestrictedLockUtils.EnforcedAdmin admin, int adminUserId) {
+ mEnforcementAdminUserId = adminUserId;
+ mEnforcedAdmin = requireNonNull(admin);
+ }
+
+ @Override
+ public void setupLearnMoreButton(Activity activity, Builder builder) {
+ String url = mStringProvider.getLearnMoreHelpPageUrl();
+ if (TextUtils.isEmpty(url)) {
+ mHelper.setupLearnMoreButtonToShowAdminPolicies(
+ activity,
+ builder,
+ mEnforcementAdminUserId,
+ mEnforcedAdmin);
+ } else {
+ mHelper.setupLearnMoreButtonToLaunchHelpPage(activity, builder, url);
+ }
+ }
+
+ @Override
+ public String getAdminSupportTitle(String restriction) {
+ if (restriction == null) {
+ return mStringProvider.getDefaultDisabledByPolicyTitle();
+ }
+ switch (restriction) {
+ case UserManager.DISALLOW_ADJUST_VOLUME:
+ return mStringProvider.getDisallowAdjustVolumeTitle();
+ case UserManager.DISALLOW_OUTGOING_CALLS:
+ return mStringProvider.getDisallowOutgoingCallsTitle();
+ case UserManager.DISALLOW_SMS:
+ return mStringProvider.getDisallowSmsTitle();
+ case DevicePolicyManager.POLICY_DISABLE_CAMERA:
+ return mStringProvider.getDisableCameraTitle();
+ case DevicePolicyManager.POLICY_DISABLE_SCREEN_CAPTURE:
+ return mStringProvider.getDisableScreenCaptureTitle();
+ case DevicePolicyManager.POLICY_SUSPEND_PACKAGES:
+ return mStringProvider.getSuspendPackagesTitle();
+ default:
+ return mStringProvider.getDefaultDisabledByPolicyTitle();
+ }
+ }
+
+ @Override
+ public CharSequence getAdminSupportContentString(Context context, CharSequence supportMessage) {
+ if (supportMessage != null) {
+ return supportMessage;
+ }
+ return mStringProvider.getDefaultDisabledByPolicyContent();
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationAccesses.java b/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationAccesses.java
index 35499c9..877dd2d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationAccesses.java
+++ b/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationAccesses.java
@@ -25,6 +25,7 @@
import android.graphics.drawable.Drawable;
import android.os.UserHandle;
import android.os.UserManager;
+import android.permission.PermissionManager;
import android.text.format.DateUtils;
import android.util.IconDrawableFactory;
import android.util.Log;
@@ -132,7 +133,8 @@
}
}
}
- if (showApp) {
+ if (showApp && PermissionManager.shouldShowPackageForIndicatorCached(mContext,
+ packageName)) {
Access access = getAccessFromOps(now, ops);
if (access != null) {
accesses.add(access);
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
index 2c2ca3b..0696916 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
@@ -80,36 +80,41 @@
@Override
public void onCapabilitiesChanged(
Network network, NetworkCapabilities networkCapabilities) {
- if (!mNetworks.contains(network.getNetId())) {
- // New network
- boolean isVcnOverWifi =
- networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
- && (Utils.tryGetWifiInfoForVcn(networkCapabilities) != null);
- boolean isWifi =
- networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI);
- if (isVcnOverWifi || isWifi) {
- mNetworks.add(network.getNetId());
- }
- }
-
+ boolean isVcnOverWifi = false;
+ boolean isWifi = false;
WifiInfo wifiInfo = null;
if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
wifiInfo = Utils.tryGetWifiInfoForVcn(networkCapabilities);
+ isVcnOverWifi = (wifiInfo != null);
} else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
wifiInfo = (WifiInfo) networkCapabilities.getTransportInfo();
+ isWifi = true;
}
- String log = new StringBuilder()
- .append(SSDF.format(System.currentTimeMillis())).append(",")
- .append("onCapabilitiesChanged: ")
- .append("network=").append(network).append(",")
- .append("networkCapabilities=").append(networkCapabilities)
- .toString();
- recordLastWifiNetwork(log);
- if (wifiInfo != null) {
- updateWifiInfo(wifiInfo);
- updateStatusLabel();
- mCallback.run();
+ // As long as it is a WiFi network, we will log it in the dumpsys for debugging.
+ if (isVcnOverWifi || isWifi) {
+ String log = new StringBuilder()
+ .append(SSDF.format(System.currentTimeMillis())).append(",")
+ .append("onCapabilitiesChanged: ")
+ .append("network=").append(network).append(",")
+ .append("networkCapabilities=").append(networkCapabilities)
+ .toString();
+ recordLastWifiNetwork(log);
}
+ // Ignore the WiFi network if it doesn't contain any valid WifiInfo, or it is not the
+ // primary WiFi.
+ if (wifiInfo == null || !wifiInfo.isPrimary()) {
+ // Remove the network from the tracking list once it becomes non-primary.
+ if (mNetworks.contains(network.getNetId())) {
+ mNetworks.remove(network.getNetId());
+ }
+ return;
+ }
+ if (!mNetworks.contains(network.getNetId())) {
+ mNetworks.add(network.getNetId());
+ }
+ updateWifiInfo(wifiInfo);
+ updateStatusLabel();
+ mCallback.run();
}
@Override
diff --git a/packages/SettingsLib/tests/robotests/Android.bp b/packages/SettingsLib/tests/robotests/Android.bp
index dc661c2..63cfe59 100644
--- a/packages/SettingsLib/tests/robotests/Android.bp
+++ b/packages/SettingsLib/tests/robotests/Android.bp
@@ -43,6 +43,8 @@
srcs: ["src/**/*.java"],
static_libs: [
"SettingsLib-robo-testutils",
+ "androidx.test.core",
+ "androidx.core_core",
],
java_resource_dirs: ["config"],
instrumentation_for: "SettingsLibShell",
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/enterprise/ActionDisabledByAdminControllerTestUtils.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/enterprise/ActionDisabledByAdminControllerTestUtils.java
new file mode 100644
index 0000000..e0c9424
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/enterprise/ActionDisabledByAdminControllerTestUtils.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.enterprise;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.Activity;
+
+import androidx.appcompat.app.AlertDialog;
+
+import com.android.settingslib.RestrictedLockUtils;
+
+/**
+ * Utils related to the action disabled by admin dialogs.
+ */
+class ActionDisabledByAdminControllerTestUtils {
+ static final int LEARN_MORE_ACTION_NONE = 0;
+ static final int LEARN_MORE_ACTION_SHOW_ADMIN_POLICIES = 1;
+ static final int LEARN_MORE_ACTION_LAUNCH_HELP_PAGE = 2;
+
+ private int mLearnMoreButtonAction = LEARN_MORE_ACTION_NONE;
+
+ ActionDisabledLearnMoreButtonLauncher createLearnMoreButtonLauncher() {
+ return new ActionDisabledLearnMoreButtonLauncher() {
+ @Override
+ public void setupLearnMoreButtonToShowAdminPolicies(Activity activity,
+ AlertDialog.Builder builder, int enforcementAdminUserId,
+ RestrictedLockUtils.EnforcedAdmin enforcedAdmin) {
+ mLearnMoreButtonAction = LEARN_MORE_ACTION_SHOW_ADMIN_POLICIES;
+ }
+
+ @Override
+ public void setupLearnMoreButtonToLaunchHelpPage(Activity activity,
+ AlertDialog.Builder builder, String url) {
+ mLearnMoreButtonAction = LEARN_MORE_ACTION_LAUNCH_HELP_PAGE;
+ }
+ };
+ }
+
+ void assertLearnMoreAction(int learnMoreActionShowAdminPolicies) {
+ assertThat(learnMoreActionShowAdminPolicies).isEqualTo(mLearnMoreButtonAction);
+ }
+
+ AlertDialog createAlertDialog(ActionDisabledByAdminController mController, Activity activity) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(activity);
+ mController.setupLearnMoreButton(activity, builder);
+ AlertDialog alertDialog = builder.create();
+ alertDialog.show();
+ return alertDialog;
+ }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/enterprise/FakeDeviceAdminStringProvider.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/enterprise/FakeDeviceAdminStringProvider.java
new file mode 100644
index 0000000..8c07d75
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/enterprise/FakeDeviceAdminStringProvider.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.enterprise;
+
+import android.annotation.Nullable;
+
+class FakeDeviceAdminStringProvider implements DeviceAdminStringProvider {
+
+ static final String DEFAULT_DISABLED_BY_POLICY_TITLE = "default_disabled_by_policy_title";
+ static final String DISALLOW_ADJUST_VOLUME_TITLE = "disallow_adjust_volume_title";
+ static final String DISALLOW_OUTGOING_CALLS_TITLE = "disallow_outgoing_calls_title";
+ static final String DISALLOW_SMS_TITLE = "disallow_sms_title";
+ static final String DISABLE_CAMERA_TITLE = "disable_camera_title";
+ static final String DISABLE_SCREEN_CAPTURE_TITLE = "disable_screen_capture_title";
+ static final String SUSPENDED_PACKAGES_TITLE = "suspended_packages_title";
+ static final String DEFAULT_DISABLED_BY_POLICY_CONTENT = "default_disabled_by_policy_content";
+ static final String DEFAULT_DISABLED_BY_POLICY_TITLE_FINANCED_DEVICE =
+ "default_disabled_by_policy_title_financed_device";
+
+ private final String mUrl;
+
+ FakeDeviceAdminStringProvider(@Nullable String url) {
+ mUrl = url;
+ }
+
+ @Override
+ public String getDefaultDisabledByPolicyTitle() {
+ return DEFAULT_DISABLED_BY_POLICY_TITLE;
+ }
+
+ @Override
+ public String getDisallowAdjustVolumeTitle() {
+ return DISALLOW_ADJUST_VOLUME_TITLE;
+ }
+
+ @Override
+ public String getDisallowOutgoingCallsTitle() {
+ return DISALLOW_OUTGOING_CALLS_TITLE;
+ }
+
+ @Override
+ public String getDisallowSmsTitle() {
+ return DISALLOW_SMS_TITLE;
+ }
+
+ @Override
+ public String getDisableCameraTitle() {
+ return DISABLE_CAMERA_TITLE;
+ }
+
+ @Override
+ public String getDisableScreenCaptureTitle() {
+ return DISABLE_SCREEN_CAPTURE_TITLE;
+ }
+
+ @Override
+ public String getSuspendPackagesTitle() {
+ return SUSPENDED_PACKAGES_TITLE;
+ }
+
+ @Override
+ public String getDefaultDisabledByPolicyContent() {
+ return DEFAULT_DISABLED_BY_POLICY_CONTENT;
+ }
+
+ @Override
+ public String getLearnMoreHelpPageUrl() {
+ return mUrl;
+ }
+
+ @Override
+ public String getDisabledByPolicyTitleForFinancedDevice() {
+ return DEFAULT_DISABLED_BY_POLICY_TITLE_FINANCED_DEVICE;
+ }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/enterprise/FinancedDeviceActionDisabledByAdminControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/enterprise/FinancedDeviceActionDisabledByAdminControllerTest.java
new file mode 100644
index 0000000..2fe2262
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/enterprise/FinancedDeviceActionDisabledByAdminControllerTest.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.enterprise;
+
+import static com.android.settingslib.enterprise.ActionDisabledByAdminControllerTestUtils.LEARN_MORE_ACTION_SHOW_ADMIN_POLICIES;
+import static com.android.settingslib.enterprise.FakeDeviceAdminStringProvider.DEFAULT_DISABLED_BY_POLICY_TITLE_FINANCED_DEVICE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.Activity;
+import android.app.Dialog;
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.UserHandle;
+
+import androidx.appcompat.app.AlertDialog;
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.settingslib.R;
+import com.android.settingslib.RestrictedLockUtils;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.android.controller.ActivityController;
+
+@RunWith(RobolectricTestRunner.class)
+public class FinancedDeviceActionDisabledByAdminControllerTest {
+ private static final int ENFORCEMENT_ADMIN_USER_ID = 123;
+ private static final ComponentName ADMIN_COMPONENT =
+ new ComponentName("some.package.name", "some.package.name.SomeClass");
+ private static final String SUPPORT_MESSAGE = "support message";
+ private static final DeviceAdminStringProvider DEVICE_ADMIN_STRING_PROVIDER =
+ new FakeDeviceAdminStringProvider(/* url = */ null);
+ private static final RestrictedLockUtils.EnforcedAdmin ENFORCED_ADMIN =
+ new RestrictedLockUtils.EnforcedAdmin(
+ ADMIN_COMPONENT, UserHandle.of(ENFORCEMENT_ADMIN_USER_ID));
+
+ private final Context mContext = ApplicationProvider.getApplicationContext();
+ private final Activity mActivity = ActivityController.of(new Activity()).get();
+ private final ActionDisabledByAdminControllerTestUtils mTestUtils =
+ new ActionDisabledByAdminControllerTestUtils();
+ private final ActionDisabledLearnMoreButtonLauncher mLauncher =
+ mTestUtils.createLearnMoreButtonLauncher();
+
+ @Before
+ public void setUp() {
+ mActivity.setTheme(R.style.Theme_AppCompat_DayNight);
+ }
+
+ @Test
+ public void setupLearnMoreButton_negativeButtonSet() {
+ FinancedDeviceActionDisabledByAdminController mController = createController(mLauncher);
+ AlertDialog alertDialog = mTestUtils.createAlertDialog(mController, mActivity);
+
+ alertDialog.getButton(Dialog.BUTTON_NEUTRAL).performClick();
+
+ mTestUtils.assertLearnMoreAction(LEARN_MORE_ACTION_SHOW_ADMIN_POLICIES);
+ }
+
+ @Test
+ public void getAdminSupportTitleResource_works() {
+ FinancedDeviceActionDisabledByAdminController mController = createController();
+
+ assertThat(mController.getAdminSupportTitle(null))
+ .isEqualTo(DEFAULT_DISABLED_BY_POLICY_TITLE_FINANCED_DEVICE);
+ }
+
+ @Test
+ public void getAdminSupportContentString_withSupportMessage_returnsSupportMessage() {
+ FinancedDeviceActionDisabledByAdminController mController = createController();
+
+ assertThat(mController.getAdminSupportContentString(mContext, SUPPORT_MESSAGE))
+ .isEqualTo(SUPPORT_MESSAGE);
+ }
+
+ @Test
+ public void getAdminSupportContentString_noSupportMessage_returnsNull() {
+ FinancedDeviceActionDisabledByAdminController mController = createController();
+
+ assertThat(mController.getAdminSupportContentString(mContext, /* supportMessage= */ null))
+ .isNull();
+ }
+
+ private FinancedDeviceActionDisabledByAdminController createController() {
+ return createController(mLauncher);
+ }
+
+ private FinancedDeviceActionDisabledByAdminController createController(
+ ActionDisabledLearnMoreButtonLauncher buttonHelper) {
+ FinancedDeviceActionDisabledByAdminController controller =
+ new FinancedDeviceActionDisabledByAdminController(
+ buttonHelper,
+ DEVICE_ADMIN_STRING_PROVIDER);
+ controller.updateEnforcedAdmin(ENFORCED_ADMIN, ENFORCEMENT_ADMIN_USER_ID);
+ return controller;
+ }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/enterprise/ManagedDeviceActionDisabledByAdminControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/enterprise/ManagedDeviceActionDisabledByAdminControllerTest.java
new file mode 100644
index 0000000..eb1dc96
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/enterprise/ManagedDeviceActionDisabledByAdminControllerTest.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.enterprise;
+
+import static com.android.settingslib.enterprise.ActionDisabledByAdminControllerTestUtils.LEARN_MORE_ACTION_LAUNCH_HELP_PAGE;
+import static com.android.settingslib.enterprise.ActionDisabledByAdminControllerTestUtils.LEARN_MORE_ACTION_SHOW_ADMIN_POLICIES;
+import static com.android.settingslib.enterprise.FakeDeviceAdminStringProvider.DEFAULT_DISABLED_BY_POLICY_CONTENT;
+import static com.android.settingslib.enterprise.FakeDeviceAdminStringProvider.DEFAULT_DISABLED_BY_POLICY_TITLE;
+import static com.android.settingslib.enterprise.FakeDeviceAdminStringProvider.DISALLOW_ADJUST_VOLUME_TITLE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.Activity;
+import android.app.Dialog;
+import android.content.ComponentName;
+import android.os.UserHandle;
+import android.os.UserManager;
+
+import androidx.appcompat.app.AlertDialog;
+
+import com.android.settingslib.R;
+import com.android.settingslib.RestrictedLockUtils;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.android.controller.ActivityController;
+
+@RunWith(RobolectricTestRunner.class)
+public class ManagedDeviceActionDisabledByAdminControllerTest {
+ private static final int ENFORCEMENT_ADMIN_USER_ID = 123;
+ private static final ComponentName ADMIN_COMPONENT =
+ new ComponentName("some.package.name", "some.package.name.SomeClass");
+ private static final String SUPPORT_MESSAGE = "support message";
+ private static final String RESTRICTION = UserManager.DISALLOW_ADJUST_VOLUME;
+ private static final String URL = "https://testexample.com";
+ private static final String EMPTY_URL = "";
+ private static final RestrictedLockUtils.EnforcedAdmin ENFORCED_ADMIN =
+ new RestrictedLockUtils.EnforcedAdmin(
+ ADMIN_COMPONENT, UserHandle.of(ENFORCEMENT_ADMIN_USER_ID));
+ private static final String SUPPORT_TITLE_FOR_RESTRICTION = DISALLOW_ADJUST_VOLUME_TITLE;
+
+ private final Activity mActivity = ActivityController.of(new Activity()).get();
+ private final ActionDisabledByAdminControllerTestUtils mTestUtils =
+ new ActionDisabledByAdminControllerTestUtils();
+ private final ActionDisabledLearnMoreButtonLauncher mLauncher =
+ mTestUtils.createLearnMoreButtonLauncher();
+
+ @Before
+ public void setUp() {
+ mActivity.setTheme(R.style.Theme_AppCompat_DayNight);
+ }
+
+ @Test
+ public void setupLearnMoreButton_validUrl_negativeButtonSet() {
+ ManagedDeviceActionDisabledByAdminController mController =
+ createController(mLauncher, URL);
+ AlertDialog alertDialog = mTestUtils.createAlertDialog(mController, mActivity);
+
+ alertDialog.getButton(Dialog.BUTTON_NEUTRAL).performClick();
+
+ mTestUtils.assertLearnMoreAction(LEARN_MORE_ACTION_LAUNCH_HELP_PAGE);
+ }
+
+ @Test
+ public void setupLearnMoreButton_noUrl_negativeButtonSet() {
+ ManagedDeviceActionDisabledByAdminController mController =
+ createController(mLauncher, EMPTY_URL);
+ AlertDialog alertDialog = mTestUtils.createAlertDialog(mController, mActivity);
+
+ alertDialog.getButton(Dialog.BUTTON_NEUTRAL).performClick();
+
+ mTestUtils.assertLearnMoreAction(LEARN_MORE_ACTION_SHOW_ADMIN_POLICIES);
+ }
+
+ @Test
+ public void getAdminSupportTitleResource_noRestriction_works() {
+ ManagedDeviceActionDisabledByAdminController mController = createController();
+
+ assertThat(mController.getAdminSupportTitle(null))
+ .isEqualTo(DEFAULT_DISABLED_BY_POLICY_TITLE);
+ }
+
+ @Test
+ public void getAdminSupportTitleResource_withRestriction_works() {
+ ManagedDeviceActionDisabledByAdminController mController = createController();
+
+ assertThat(mController.getAdminSupportTitle(RESTRICTION))
+ .isEqualTo(SUPPORT_TITLE_FOR_RESTRICTION);
+ }
+
+ @Test
+ public void getAdminSupportContentString_withSupportMessage_returnsSupportMessage() {
+ ManagedDeviceActionDisabledByAdminController mController = createController();
+
+ assertThat(mController.getAdminSupportContentString(mActivity, SUPPORT_MESSAGE))
+ .isEqualTo(SUPPORT_MESSAGE);
+ }
+
+ @Test
+ public void getAdminSupportContentString_noSupportMessage_returnsDefault() {
+ ManagedDeviceActionDisabledByAdminController mController = createController();
+
+ assertThat(mController.getAdminSupportContentString(mActivity, /* supportMessage= */ null))
+ .isEqualTo(DEFAULT_DISABLED_BY_POLICY_CONTENT);
+ }
+
+ private ManagedDeviceActionDisabledByAdminController createController() {
+ return createController(mLauncher, /* url= */ null);
+ }
+
+ private ManagedDeviceActionDisabledByAdminController createController(
+ ActionDisabledLearnMoreButtonLauncher buttonHelper, String url) {
+ ManagedDeviceActionDisabledByAdminController controller =
+ new ManagedDeviceActionDisabledByAdminController(
+ buttonHelper,
+ new FakeDeviceAdminStringProvider(url));
+ controller.updateEnforcedAdmin(ENFORCED_ADMIN, ENFORCEMENT_ADMIN_USER_ID);
+ return controller;
+ }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/ActionButtonsPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/ActionButtonsPreferenceTest.java
index e24b525..9f31cef 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/ActionButtonsPreferenceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/ActionButtonsPreferenceTest.java
@@ -48,7 +48,7 @@
@Before
public void setUp() {
mContext = RuntimeEnvironment.application;
- mRootView = View.inflate(mContext, R.layout.settings_action_buttons, null /* parent */);
+ mRootView = View.inflate(mContext, R.layout.settingslib_action_buttons, null /* parent */);
mHolder = PreferenceViewHolder.createInstanceForTests(mRootView);
mPref = new ActionButtonsPreference(mContext);
}
@@ -251,6 +251,114 @@
assertThat(drawablesAroundText[1 /* top */]).isNull();
}
+ @Test
+ public void onBindViewHolder_setAllButton_shouldShowAllDivider() {
+ mPref.setButton1Text(R.string.install_other_apps);
+ mPref.setButton2Text(R.string.install_other_apps);
+ mPref.setButton3Text(R.string.install_other_apps);
+ mPref.setButton4Text(R.string.install_other_apps);
+
+ mPref.onBindViewHolder(mHolder);
+
+ assertThat(mRootView.findViewById(R.id.divider1).getVisibility())
+ .isEqualTo(View.VISIBLE);
+ assertThat(mRootView.findViewById(R.id.divider2).getVisibility())
+ .isEqualTo(View.VISIBLE);
+ assertThat(mRootView.findViewById(R.id.divider3).getVisibility())
+ .isEqualTo(View.VISIBLE);
+ }
+
+ @Test
+ public void onBindViewHolder_setAllButtonWithoutButton2_shouldHideDivider1() {
+ mPref.setButton1Text(R.string.install_other_apps);
+ mPref.setButton3Text(R.string.install_other_apps);
+ mPref.setButton4Text(R.string.install_other_apps);
+
+ mPref.onBindViewHolder(mHolder);
+
+ assertThat(mRootView.findViewById(R.id.divider1).getVisibility())
+ .isEqualTo(View.GONE);
+ assertThat(mRootView.findViewById(R.id.divider2).getVisibility())
+ .isEqualTo(View.VISIBLE);
+ assertThat(mRootView.findViewById(R.id.divider3).getVisibility())
+ .isEqualTo(View.VISIBLE);
+ }
+
+ @Test
+ public void onBindViewHolder_setAllButtonWithoutButton3_shouldHideDivider2() {
+ mPref.setButton1Text(R.string.install_other_apps);
+ mPref.setButton2Text(R.string.install_other_apps);
+ mPref.setButton4Text(R.string.install_other_apps);
+
+ mPref.onBindViewHolder(mHolder);
+
+ assertThat(mRootView.findViewById(R.id.divider1).getVisibility())
+ .isEqualTo(View.VISIBLE);
+ assertThat(mRootView.findViewById(R.id.divider2).getVisibility())
+ .isEqualTo(View.GONE);
+ assertThat(mRootView.findViewById(R.id.divider3).getVisibility())
+ .isEqualTo(View.VISIBLE);
+ }
+
+ @Test
+ public void onBindViewHolder_setButton1And4_shouldShowDivider3Only() {
+ mPref.setButton1Text(R.string.install_other_apps);
+ mPref.setButton4Text(R.string.install_other_apps);
+
+ mPref.onBindViewHolder(mHolder);
+
+ assertThat(mRootView.findViewById(R.id.divider1).getVisibility())
+ .isEqualTo(View.GONE);
+ assertThat(mRootView.findViewById(R.id.divider2).getVisibility())
+ .isEqualTo(View.GONE);
+ assertThat(mRootView.findViewById(R.id.divider3).getVisibility())
+ .isEqualTo(View.VISIBLE);
+ }
+
+ @Test
+ public void onBindViewHolder_setOneButtonOnly_noDivider() {
+ mPref.setButton4Text(R.string.install_other_apps);
+
+ mPref.onBindViewHolder(mHolder);
+
+ assertThat(mRootView.findViewById(R.id.divider1).getVisibility())
+ .isEqualTo(View.GONE);
+ assertThat(mRootView.findViewById(R.id.divider2).getVisibility())
+ .isEqualTo(View.GONE);
+ assertThat(mRootView.findViewById(R.id.divider3).getVisibility())
+ .isEqualTo(View.GONE);
+ }
+
+ @Test
+ public void onBindViewHolder_setButton1And2_shouldShowDivider1Only() {
+ mPref.setButton1Text(R.string.install_other_apps);
+ mPref.setButton2Text(R.string.install_other_apps);
+
+ mPref.onBindViewHolder(mHolder);
+
+ assertThat(mRootView.findViewById(R.id.divider1).getVisibility())
+ .isEqualTo(View.VISIBLE);
+ assertThat(mRootView.findViewById(R.id.divider2).getVisibility())
+ .isEqualTo(View.GONE);
+ assertThat(mRootView.findViewById(R.id.divider3).getVisibility())
+ .isEqualTo(View.GONE);
+ }
+
+ @Test
+ public void onBindViewHolder_setButton1And3_shouldShowDivider2Only() {
+ mPref.setButton1Text(R.string.install_other_apps);
+ mPref.setButton3Text(R.string.install_other_apps);
+
+ mPref.onBindViewHolder(mHolder);
+
+ assertThat(mRootView.findViewById(R.id.divider1).getVisibility())
+ .isEqualTo(View.GONE);
+ assertThat(mRootView.findViewById(R.id.divider2).getVisibility())
+ .isEqualTo(View.VISIBLE);
+ assertThat(mRootView.findViewById(R.id.divider3).getVisibility())
+ .isEqualTo(View.GONE);
+ }
+
public static ActionButtonsPreference createMock() {
final ActionButtonsPreference pref = mock(ActionButtonsPreference.class);
when(pref.setButton1Text(anyInt())).thenReturn(pref);
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/BannerMessagePreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/BannerMessagePreferenceTest.java
index 8ab0298..6670ed3 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/BannerMessagePreferenceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/BannerMessagePreferenceTest.java
@@ -18,18 +18,35 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
import android.content.Context;
+import android.graphics.ColorFilter;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
+import android.graphics.drawable.Drawable;
+import android.os.Build;
+import android.util.AttributeSet;
import android.view.View;
import android.widget.Button;
+import android.widget.ImageButton;
+import android.widget.ImageView;
import android.widget.TextView;
+import androidx.annotation.ColorRes;
import androidx.preference.PreferenceViewHolder;
+import androidx.preference.R;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
+import org.robolectric.Shadows;
+import org.robolectric.shadows.ShadowDrawable;
+import org.robolectric.util.ReflectionHelpers;
@RunWith(RobolectricTestRunner.class)
public class BannerMessagePreferenceTest {
@@ -39,16 +56,22 @@
private BannerMessagePreference mBannerPreference;
private PreferenceViewHolder mHolder;
+ private boolean mClickListenerCalled = false;
+ private final View.OnClickListener mClickListener = v -> mClickListenerCalled = true;
+
+ private static final int TEST_STRING_RES_ID =
+ R.string.accessibility_banner_message_dismiss;
+
@Before
public void setUp() {
mContext = RuntimeEnvironment.application;
- mRootView = View.inflate(mContext, R.layout.banner_message, null /* parent */);
- mHolder = PreferenceViewHolder.createInstanceForTests(mRootView);
+ mClickListenerCalled = false;
mBannerPreference = new BannerMessagePreference(mContext);
+ setUpViewHolder();
}
@Test
- public void onBindViewHolder_shouldSetTitle() {
+ public void onBindViewHolder_whenTitleSet_shouldSetTitle() {
mBannerPreference.setTitle("test");
mBannerPreference.onBindViewHolder(mHolder);
@@ -58,7 +81,7 @@
}
@Test
- public void onBindViewHolder_shouldSetSummary() {
+ public void onBindViewHolder_whenSummarySet_shouldSetSummary() {
mBannerPreference.setSummary("test");
mBannerPreference.onBindViewHolder(mHolder);
@@ -68,30 +91,114 @@
}
@Test
- public void setPositiveButtonText_shouldShowPositiveButton() {
- mBannerPreference.setPositiveButtonText(R.string.tts_settings_title);
+ public void onBindViewHolder_whenPreS_shouldBindView() {
+ assumeAndroidR();
+ mBannerPreference.setSummary("test");
mBannerPreference.onBindViewHolder(mHolder);
- assertThat(((Button) mRootView.findViewById(R.id.banner_positive_btn)).getVisibility())
- .isEqualTo(View.VISIBLE);
+ assertThat(((TextView) mRootView.findViewById(R.id.banner_summary)).getText())
+ .isEqualTo("test");
+ }
+
+ @Test
+ public void onBindViewHolder_whenAtLeastS_whenSubtitleSetByString_shouldSetSubtitle() {
+ assumeAndroidS();
+ mBannerPreference.setSubtitle("test");
+
+ mBannerPreference.onBindViewHolder(mHolder);
+
+ TextView mSubtitleView = mRootView.findViewById(R.id.banner_subtitle);
+ assertThat(mSubtitleView.getText()).isEqualTo("test");
+ assertThat(mSubtitleView.getVisibility()).isEqualTo(View.VISIBLE);
+ }
+
+ @Test
+ public void onBindViewHolder_whenAtLeastS_whenSubtitleSetByResId_shouldSetSubtitle() {
+ assumeAndroidS();
+ mBannerPreference.setSubtitle(TEST_STRING_RES_ID);
+
+ mBannerPreference.onBindViewHolder(mHolder);
+
+ TextView mSubtitleView = mRootView.findViewById(R.id.banner_subtitle);
+ assertThat(mSubtitleView.getText()).isEqualTo(mContext.getString(TEST_STRING_RES_ID));
+ assertThat(mSubtitleView.getVisibility()).isEqualTo(View.VISIBLE);
+ }
+
+ @Test
+ public void onBindViewHolder_whenAtLeastS_whenSubtitleXmlAttribute_shouldSetSubtitle() {
+ assumeAndroidS();
+ AttributeSet mAttributeSet = Robolectric.buildAttributeSet()
+ .addAttribute(R.attr.subtitle, "Test")
+ .build();
+ mBannerPreference = new BannerMessagePreference(mContext, mAttributeSet);
+
+ mBannerPreference.onBindViewHolder(mHolder);
+
+ TextView mSubtitleView = mRootView.findViewById(R.id.banner_subtitle);
+ assertThat(mSubtitleView.getText()).isEqualTo("Test");
+ assertThat(mSubtitleView.getVisibility()).isEqualTo(View.VISIBLE);
+ }
+
+ @Test
+ public void onBindViewHolder_whenAtLeastS_shouldNotShowSubtitleIfUnset() {
+ assumeAndroidS();
+ mBannerPreference.onBindViewHolder(mHolder);
+
+ TextView mSubtitleView = mRootView.findViewById(R.id.banner_subtitle);
+ assertThat(mSubtitleView.getVisibility()).isEqualTo(View.GONE);
+ }
+
+ @Test
+ public void onBindViewHolder_whenAtLeastS_whenIconSet_shouldSetIcon() {
+ assumeAndroidS();
+ mBannerPreference.setIcon(R.drawable.settingslib_ic_cross);
+
+ mBannerPreference.onBindViewHolder(mHolder);
+
+ ImageView mIcon = mRootView.findViewById(R.id.banner_icon);
+ ShadowDrawable shadowDrawable = Shadows.shadowOf(mIcon.getDrawable());
+ assertThat(shadowDrawable.getCreatedFromResId())
+ .isEqualTo(R.drawable.settingslib_ic_cross);
+ }
+
+ @Test
+ public void onBindViewHolder_whenAtLeastS_whenNoIconSet_shouldSetIconToDefault() {
+ assumeAndroidS();
+ mBannerPreference.onBindViewHolder(mHolder);
+
+ ImageView mIcon = mRootView.findViewById(R.id.banner_icon);
+ ShadowDrawable shadowDrawable = Shadows.shadowOf(mIcon.getDrawable());
+ assertThat(shadowDrawable.getCreatedFromResId()).isEqualTo(R.drawable.ic_warning);
+ }
+
+ @Test
+ public void setPositiveButtonText_shouldShowPositiveButton() {
+ mBannerPreference.setPositiveButtonText(TEST_STRING_RES_ID);
+
+ mBannerPreference.onBindViewHolder(mHolder);
+
+ Button mPositiveButton = mRootView.findViewById(R.id.banner_positive_btn);
+ assertThat(mPositiveButton.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mPositiveButton.getText()).isEqualTo(mContext.getString(TEST_STRING_RES_ID));
}
@Test
public void setNegativeButtonText_shouldShowNegativeButton() {
- mBannerPreference.setNegativeButtonText(R.string.tts_settings_title);
+ mBannerPreference.setNegativeButtonText(TEST_STRING_RES_ID);
mBannerPreference.onBindViewHolder(mHolder);
- assertThat(((Button) mRootView.findViewById(R.id.banner_negative_btn)).getVisibility())
- .isEqualTo(View.VISIBLE);
+ Button mNegativeButton = mRootView.findViewById(R.id.banner_negative_btn);
+ assertThat(mNegativeButton.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mNegativeButton.getText()).isEqualTo(mContext.getString(TEST_STRING_RES_ID));
}
@Test
public void withoutSetPositiveButtonText_shouldHidePositiveButton() {
mBannerPreference.onBindViewHolder(mHolder);
- assertThat(((Button) mRootView.findViewById(R.id.banner_positive_btn)).getVisibility())
+ assertThat(mRootView.findViewById(R.id.banner_positive_btn).getVisibility())
.isEqualTo(View.GONE);
}
@@ -99,51 +206,290 @@
public void withoutSetNegativeButtonText_shouldHideNegativeButton() {
mBannerPreference.onBindViewHolder(mHolder);
- assertThat(((Button) mRootView.findViewById(R.id.banner_negative_btn)).getVisibility())
+ assertThat(mRootView.findViewById(R.id.banner_negative_btn).getVisibility())
.isEqualTo(View.GONE);
}
@Test
public void setPositiveButtonVisible_withTrue_shouldShowPositiveButton() {
- mBannerPreference.setPositiveButtonText(R.string.tts_settings_title);
+ mBannerPreference.setPositiveButtonText(TEST_STRING_RES_ID);
mBannerPreference.setPositiveButtonVisible(true);
mBannerPreference.onBindViewHolder(mHolder);
- assertThat(((Button) mRootView.findViewById(R.id.banner_positive_btn)).getVisibility())
+ assertThat((mRootView.findViewById(R.id.banner_positive_btn)).getVisibility())
.isEqualTo(View.VISIBLE);
}
@Test
public void setPositiveButtonVisible_withFalse_shouldHidePositiveButton() {
- mBannerPreference.setPositiveButtonText(R.string.tts_settings_title);
+ mBannerPreference.setPositiveButtonText(TEST_STRING_RES_ID);
mBannerPreference.setPositiveButtonVisible(false);
mBannerPreference.onBindViewHolder(mHolder);
- assertThat(((Button) mRootView.findViewById(R.id.banner_positive_btn)).getVisibility())
+ assertThat(mRootView.findViewById(R.id.banner_positive_btn).getVisibility())
.isEqualTo(View.GONE);
}
@Test
public void setNegativeButtonVisible_withTrue_shouldShowNegativeButton() {
- mBannerPreference.setNegativeButtonText(R.string.tts_settings_title);
+ mBannerPreference.setNegativeButtonText(TEST_STRING_RES_ID);
mBannerPreference.setNegativeButtonVisible(true);
mBannerPreference.onBindViewHolder(mHolder);
- assertThat(((Button) mRootView.findViewById(R.id.banner_negative_btn)).getVisibility())
+ assertThat(mRootView.findViewById(R.id.banner_negative_btn).getVisibility())
.isEqualTo(View.VISIBLE);
}
@Test
public void setNegativeButtonVisible_withFalse_shouldHideNegativeButton() {
- mBannerPreference.setNegativeButtonText(R.string.tts_settings_title);
+ mBannerPreference.setNegativeButtonText(TEST_STRING_RES_ID);
mBannerPreference.setNegativeButtonVisible(false);
mBannerPreference.onBindViewHolder(mHolder);
- assertThat(((Button) mRootView.findViewById(R.id.banner_negative_btn)).getVisibility())
+ assertThat(mRootView.findViewById(R.id.banner_negative_btn).getVisibility())
.isEqualTo(View.GONE);
}
+
+ @Test
+ public void setPositiveButtonOnClickListener_setsClickListener() {
+ mBannerPreference.setPositiveButtonOnClickListener(mClickListener);
+
+ mBannerPreference.onBindViewHolder(mHolder);
+ mRootView.findViewById(R.id.banner_positive_btn).callOnClick();
+
+ assertThat(mClickListenerCalled).isTrue();
+ }
+
+ @Test
+ public void setNegativeButtonOnClickListener_setsClickListener() {
+ mBannerPreference.setNegativeButtonOnClickListener(mClickListener);
+
+ mBannerPreference.onBindViewHolder(mHolder);
+ mRootView.findViewById(R.id.banner_negative_btn).callOnClick();
+
+ assertThat(mClickListenerCalled).isTrue();
+ }
+
+ @Test
+ public void setDismissButtonOnClickListener_whenAtLeastS_setsClickListener() {
+ assumeAndroidS();
+ mBannerPreference.setDismissButtonOnClickListener(mClickListener);
+
+ mBannerPreference.onBindViewHolder(mHolder);
+ mRootView.findViewById(R.id.banner_dismiss_btn).callOnClick();
+
+ assertThat(mClickListenerCalled).isTrue();
+ }
+
+ @Test
+ public void onBindViewHolder_whenAtLeastS_withDismissOnClickListener_dismissIsVisible() {
+ assumeAndroidS();
+ mBannerPreference.setDismissButtonOnClickListener(mClickListener);
+
+ mBannerPreference.onBindViewHolder(mHolder);
+
+ assertThat((mRootView.findViewById(R.id.banner_dismiss_btn)).getVisibility())
+ .isEqualTo(View.VISIBLE);
+ }
+
+ @Test
+ public void onBindViewHolder_whenAtLeastS_withNoDismissClickListener_dimissButtonIsGone() {
+ assumeAndroidS();
+
+ mBannerPreference.onBindViewHolder(mHolder);
+
+ assertThat((mRootView.findViewById(R.id.banner_dismiss_btn)).getVisibility())
+ .isEqualTo(View.GONE);
+ }
+
+ @Test
+ public void onBindViewHolder_whenAtLeastS_withNoClickListenerAndVisible_dimissButtonIsGone() {
+ assumeAndroidS();
+ mBannerPreference.setDismissButtonVisible(true);
+
+ mBannerPreference.onBindViewHolder(mHolder);
+
+ assertThat(mRootView.findViewById(R.id.banner_dismiss_btn).getVisibility())
+ .isEqualTo(View.GONE);
+ }
+
+ @Test
+ public void onBindViewHolder_whenAtLeastS_withClickListenerAndNotVisible_dimissButtonIsGone() {
+ assumeAndroidS();
+ mBannerPreference.setDismissButtonOnClickListener(mClickListener);
+ mBannerPreference.setDismissButtonVisible(false);
+
+ mBannerPreference.onBindViewHolder(mHolder);
+
+ ImageButton mDismissButton = mRootView.findViewById(R.id.banner_dismiss_btn);
+ assertThat(mDismissButton.getVisibility()).isEqualTo(View.GONE);
+ }
+
+ @Test
+ public void onBindViewHolder_whenAtLeastS_whenAttentionUnset_setsHighTheme() {
+ assumeAndroidS();
+ Drawable mCardBackgroundSpy = spy(mRootView.getBackground());
+ mRootView.setBackground(mCardBackgroundSpy);
+
+ mBannerPreference.onBindViewHolder(mHolder);
+
+ assertThat(((ImageView) mHolder.findViewById(R.id.banner_icon)).getColorFilter())
+ .isEqualTo(getColorFilter(R.color.banner_accent_attention_high));
+ assertThat(getButtonColor(R.id.banner_positive_btn))
+ .isEqualTo(getColorId(R.color.banner_accent_attention_high));
+ assertThat(getButtonColor(R.id.banner_negative_btn))
+ .isEqualTo(getColorId(R.color.banner_accent_attention_high));
+ verify(mCardBackgroundSpy).setTint(getColorId(R.color.banner_background_attention_high));
+ }
+
+ @Test
+ public void onBindViewHolder_whenAtLeastS_whenAttentionHighByXML_setsHighTheme() {
+ assumeAndroidS();
+ Drawable mCardBackgroundSpy = spy(mRootView.getBackground());
+ mRootView.setBackground(mCardBackgroundSpy);
+ AttributeSet mAttributeSet = Robolectric.buildAttributeSet()
+ .addAttribute(R.attr.attentionLevel, "high")
+ .build();
+ mBannerPreference = new BannerMessagePreference(mContext, mAttributeSet);
+
+ mBannerPreference.onBindViewHolder(mHolder);
+
+ assertThat(((ImageView) mHolder.findViewById(R.id.banner_icon)).getColorFilter())
+ .isEqualTo(getColorFilter(R.color.banner_accent_attention_high));
+ assertThat(getButtonColor(R.id.banner_positive_btn))
+ .isEqualTo(getColorId(R.color.banner_accent_attention_high));
+ assertThat(getButtonColor(R.id.banner_negative_btn))
+ .isEqualTo(getColorId(R.color.banner_accent_attention_high));
+ verify(mCardBackgroundSpy).setTint(getColorId(R.color.banner_background_attention_high));
+ }
+
+ @Test
+ public void onBindViewHolder_whenAtLeastS_whenAttentionMediumByXML_setsMediumTheme() {
+ assumeAndroidS();
+ Drawable mCardBackgroundSpy = spy(mRootView.getBackground());
+ mRootView.setBackground(mCardBackgroundSpy);
+ AttributeSet mAttributeSet = Robolectric.buildAttributeSet()
+ .addAttribute(R.attr.attentionLevel, "medium")
+ .build();
+ mBannerPreference = new BannerMessagePreference(mContext, mAttributeSet);
+
+ mBannerPreference.onBindViewHolder(mHolder);
+
+ assertThat(((ImageView) mHolder.findViewById(R.id.banner_icon)).getColorFilter())
+ .isEqualTo(getColorFilter(R.color.banner_accent_attention_medium));
+ assertThat(getButtonColor(R.id.banner_positive_btn))
+ .isEqualTo(getColorId(R.color.banner_accent_attention_medium));
+ assertThat(getButtonColor(R.id.banner_negative_btn))
+ .isEqualTo(getColorId(R.color.banner_accent_attention_medium));
+ verify(mCardBackgroundSpy).setTint(getColorId(R.color.banner_background_attention_medium));
+ }
+
+ @Test
+ public void onBindViewHolder_whenAtLeastS_whenAttentionLowByXML_setsLowTheme() {
+ assumeAndroidS();
+ Drawable mCardBackgroundSpy = spy(mRootView.getBackground());
+ mRootView.setBackground(mCardBackgroundSpy);
+ AttributeSet mAttributeSet = Robolectric.buildAttributeSet()
+ .addAttribute(R.attr.attentionLevel, "low")
+ .build();
+ mBannerPreference = new BannerMessagePreference(mContext, mAttributeSet);
+
+ mBannerPreference.onBindViewHolder(mHolder);
+
+ assertThat(((ImageView) mHolder.findViewById(R.id.banner_icon)).getColorFilter())
+ .isEqualTo(getColorFilter(R.color.banner_accent_attention_low));
+ assertThat(getButtonColor(R.id.banner_positive_btn))
+ .isEqualTo(getColorId(R.color.banner_accent_attention_low));
+ assertThat(getButtonColor(R.id.banner_negative_btn))
+ .isEqualTo(getColorId(R.color.banner_accent_attention_low));
+ verify(mCardBackgroundSpy).setTint(getColorId(R.color.banner_background_attention_low));
+ }
+
+ @Test
+ public void setAttentionLevel_whenAtLeastS_whenHighAttention_setsHighTheme() {
+ assumeAndroidS();
+ Drawable mCardBackgroundSpy = spy(mRootView.getBackground());
+ mRootView.setBackground(mCardBackgroundSpy);
+ mBannerPreference.setAttentionLevel(BannerMessagePreference.AttentionLevel.HIGH);
+
+ mBannerPreference.onBindViewHolder(mHolder);
+
+ assertThat(((ImageView) mHolder.findViewById(R.id.banner_icon)).getColorFilter())
+ .isEqualTo(getColorFilter(R.color.banner_accent_attention_high));
+ assertThat(getButtonColor(R.id.banner_positive_btn))
+ .isEqualTo(getColorId(R.color.banner_accent_attention_high));
+ assertThat(getButtonColor(R.id.banner_negative_btn))
+ .isEqualTo(getColorId(R.color.banner_accent_attention_high));
+ verify(mCardBackgroundSpy).setTint(getColorId(R.color.banner_background_attention_high));
+ }
+
+ @Test
+ public void setAttentionLevel_whenAtLeastS_whenMedAttention_setsMediumTheme() {
+ assumeAndroidS();
+ Drawable mCardBackgroundSpy = spy(mRootView.getBackground());
+ mRootView.setBackground(mCardBackgroundSpy);
+ mBannerPreference.setAttentionLevel(BannerMessagePreference.AttentionLevel.MEDIUM);
+
+ mBannerPreference.onBindViewHolder(mHolder);
+
+ assertThat(((ImageView) mHolder.findViewById(R.id.banner_icon)).getColorFilter())
+ .isEqualTo(getColorFilter(R.color.banner_accent_attention_medium));
+ assertThat(getButtonColor(R.id.banner_positive_btn))
+ .isEqualTo(getColorId(R.color.banner_accent_attention_medium));
+ assertThat(getButtonColor(R.id.banner_negative_btn))
+ .isEqualTo(getColorId(R.color.banner_accent_attention_medium));
+ verify(mCardBackgroundSpy).setTint(getColorId(R.color.banner_background_attention_medium));
+ }
+
+ @Test
+ public void setAttentionLevel_whenAtLeastS_whenLowAttention_setsLowTheme() {
+ assumeAndroidS();
+ Drawable mCardBackgroundSpy = spy(mRootView.getBackground());
+ mRootView.setBackground(mCardBackgroundSpy);
+ mBannerPreference.setAttentionLevel(BannerMessagePreference.AttentionLevel.LOW);
+
+ mBannerPreference.onBindViewHolder(mHolder);
+
+ assertThat(((ImageView) mHolder.findViewById(R.id.banner_icon)).getColorFilter())
+ .isEqualTo(getColorFilter(R.color.banner_accent_attention_low));
+ assertThat(getButtonColor(R.id.banner_positive_btn))
+ .isEqualTo(getColorId(R.color.banner_accent_attention_low));
+ assertThat(getButtonColor(R.id.banner_negative_btn))
+ .isEqualTo(getColorId(R.color.banner_accent_attention_low));
+ verify(mCardBackgroundSpy).setTint(getColorId(R.color.banner_background_attention_low));
+ }
+
+ private int getButtonColor(int buttonResId) {
+ Button mButton = mRootView.findViewById(buttonResId);
+ return mButton.getTextColors().getDefaultColor();
+ }
+
+ private ColorFilter getColorFilter(@ColorRes int colorResId) {
+ return new PorterDuffColorFilter(getColorId(colorResId), PorterDuff.Mode.SRC_IN);
+ }
+
+ private int getColorId(@ColorRes int colorResId) {
+ return mContext.getResources().getColor(colorResId, mContext.getTheme());
+ }
+
+ private void assumeAndroidR() {
+ ReflectionHelpers.setStaticField(Build.VERSION.class, "SDK_INT", 30);
+ // Reset view holder to use correct layout.
+ }
+
+ private void assumeAndroidS() {
+ ReflectionHelpers.setStaticField(Build.VERSION.class, "SDK_INT", 31);
+ // Re-inflate view to update layout.
+ setUpViewHolder();
+ }
+
+ private void setUpViewHolder() {
+ mRootView =
+ View.inflate(mContext, mBannerPreference.getLayoutResource(), null /* parent */);
+ mHolder = PreferenceViewHolder.createInstanceForTests(mRootView);
+ }
}
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index ccbcb89..8e6e251f 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -251,7 +251,7 @@
<integer name="def_accessibility_magnification_capabilities">3</integer>
<!-- Default for Settings.Global.DEVELOPMENT_ENABLE_NON_RESIZABLE_MULTI_WINDOW -->
- <bool name="def_enable_non_resizable_multi_window">true</bool>
+ <bool name="def_enable_non_resizable_multi_window">false</bool>
<!-- Default for Settings.Secure.ACCESSIBILITY_BUTTON_MODE -->
<integer name="def_accessibility_button_mode">1</integer>
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java
index b7560d2..c9c3db8 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java
@@ -73,6 +73,7 @@
Settings.Global.CUSTOM_BUGREPORT_HANDLER_USER,
Settings.Global.DEVELOPMENT_SETTINGS_ENABLED,
Settings.Global.USER_DISABLED_HDR_FORMATS,
- Settings.Global.ARE_USER_DISABLED_HDR_FORMATS_ALLOWED
+ Settings.Global.ARE_USER_DISABLED_HDR_FORMATS_ALLOWED,
+ Settings.Global.DEVICE_CONFIG_SYNC_DISABLED,
};
}
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
index 1cfdff8..cf54083 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
@@ -190,5 +190,7 @@
Settings.Secure.ACCESSIBILITY_FLOATING_MENU_FADE_ENABLED,
Settings.Secure.NOTIFICATION_BUBBLES,
Settings.Secure.LOCATION_TIME_ZONE_DETECTION_ENABLED,
+ Settings.Secure.LOCKSCREEN_SHOW_CONTROLS,
+ Settings.Secure.LOCKSCREEN_SHOW_WALLET,
};
}
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
index 8f7f1fa..5220a04 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
@@ -139,6 +139,7 @@
/* first= */Global.ONE_HANDED_KEYGUARD_SIDE_LEFT,
/* last= */Global.ONE_HANDED_KEYGUARD_SIDE_RIGHT));
VALIDATORS.put(Global.DISABLE_WINDOW_BLURS, BOOLEAN_VALIDATOR);
+ VALIDATORS.put(Global.DEVICE_CONFIG_SYNC_DISABLED, BOOLEAN_VALIDATOR);
}
}
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
index 36f5dba..50fab4f 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
@@ -146,6 +146,8 @@
VALIDATORS.put(Secure.QS_TILES, TILE_LIST_VALIDATOR);
VALIDATORS.put(Secure.CONTROLS_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.POWER_MENU_LOCKED_SHOW_CONTENT, BOOLEAN_VALIDATOR);
+ VALIDATORS.put(Secure.LOCKSCREEN_SHOW_CONTROLS, BOOLEAN_VALIDATOR);
+ VALIDATORS.put(Secure.LOCKSCREEN_SHOW_WALLET, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.DOZE_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.DOZE_ALWAYS_ON, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.DOZE_PICK_UP_GESTURE, BOOLEAN_VALIDATOR);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java b/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java
index df6ff73..00fd19c 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java
@@ -16,7 +16,11 @@
package com.android.providers.settings;
-import android.annotation.SystemApi;
+import static android.provider.Settings.Config.SYNC_DISABLED_MODE_NONE;
+import static android.provider.Settings.Config.SYNC_DISABLED_MODE_PERSISTENT;
+import static android.provider.Settings.Config.SYNC_DISABLED_MODE_UNTIL_REBOOT;
+
+import android.annotation.SuppressLint;
import android.app.ActivityManager;
import android.content.AttributionSource;
import android.content.IContentProvider;
@@ -41,10 +45,7 @@
/**
* Receives shell commands from the command line related to device config flags, and dispatches them
* to the SettingsProvider.
- *
- * @hide
*/
-@SystemApi
public final class DeviceConfigService extends Binder {
final SettingsProvider mProvider;
@@ -62,18 +63,20 @@
final SettingsProvider mProvider;
enum CommandVerb {
- UNSPECIFIED,
GET,
PUT,
DELETE,
LIST,
RESET,
+ SET_SYNC_DISABLED_FOR_TESTS,
+ IS_SYNC_DISABLED_FOR_TESTS,
}
MyShellCommand(SettingsProvider provider) {
mProvider = provider;
}
+ @SuppressLint("AndroidFrameworkRequiresPermission")
@Override
public int onCommand(String cmd) {
if (cmd == null || "help".equals(cmd) || "-h".equals(cmd)) {
@@ -83,6 +86,7 @@
final PrintWriter perr = getErrPrintWriter();
boolean isValid = false;
+
CommandVerb verb;
if ("get".equalsIgnoreCase(cmd)) {
verb = CommandVerb.GET;
@@ -97,21 +101,33 @@
}
} else if ("reset".equalsIgnoreCase(cmd)) {
verb = CommandVerb.RESET;
+ } else if ("set_sync_disabled_for_tests".equalsIgnoreCase(cmd)) {
+ verb = CommandVerb.SET_SYNC_DISABLED_FOR_TESTS;
+ } else if ("is_sync_disabled_for_tests".equalsIgnoreCase(cmd)) {
+ verb = CommandVerb.IS_SYNC_DISABLED_FOR_TESTS;
+ if (peekNextArg() != null) {
+ perr.println("Bad arguments");
+ return -1;
+ }
+ isValid = true;
} else {
// invalid
perr.println("Invalid command: " + cmd);
return -1;
}
+ // Parse args for those commands that have them.
+ int disableSyncMode = -1;
int resetMode = -1;
boolean makeDefault = false;
String namespace = null;
String key = null;
String value = null;
- String arg = null;
+ String arg;
while ((arg = getNextArg()) != null) {
if (verb == CommandVerb.RESET) {
if (resetMode == -1) {
+ // RESET 1st arg (required)
if ("untrusted_defaults".equalsIgnoreCase(arg)) {
resetMode = Settings.RESET_MODE_UNTRUSTED_DEFAULTS;
} else if ("untrusted_clear".equalsIgnoreCase(arg)) {
@@ -127,6 +143,7 @@
isValid = true;
}
} else {
+ // RESET 2nd arg (optional)
namespace = arg;
if (peekNextArg() == null) {
isValid = true;
@@ -136,7 +153,26 @@
return -1;
}
}
+ } else if (verb == CommandVerb.SET_SYNC_DISABLED_FOR_TESTS) {
+ if (disableSyncMode == -1) {
+ // DISABLE_SYNC_FOR_TESTS 1st arg (required)
+ if ("none".equalsIgnoreCase(arg)) {
+ disableSyncMode = SYNC_DISABLED_MODE_NONE;
+ } else if ("persistent".equalsIgnoreCase(arg)) {
+ disableSyncMode = SYNC_DISABLED_MODE_PERSISTENT;
+ } else if ("until_reboot".equalsIgnoreCase(arg)) {
+ disableSyncMode = SYNC_DISABLED_MODE_UNTIL_REBOOT;
+ } else {
+ // invalid
+ perr.println("Invalid sync disabled mode: " + arg);
+ return -1;
+ }
+ if (peekNextArg() == null) {
+ isValid = true;
+ }
+ }
} else if (namespace == null) {
+ // GET, PUT, DELETE, LIST 1st arg
namespace = arg;
if (verb == CommandVerb.LIST) {
if (peekNextArg() == null) {
@@ -148,8 +184,10 @@
}
}
} else if (key == null) {
+ // GET, PUT, DELETE 2nd arg
key = arg;
if ((verb == CommandVerb.GET || verb == CommandVerb.DELETE)) {
+ // GET, DELETE only have 2 args
if (peekNextArg() == null) {
isValid = true;
} else {
@@ -159,11 +197,13 @@
}
}
} else if (value == null) {
+ // PUT 3rd arg (required)
value = arg;
if (verb == CommandVerb.PUT && peekNextArg() == null) {
isValid = true;
}
} else if ("default".equalsIgnoreCase(arg)) {
+ // PUT 4th arg (optional)
makeDefault = true;
if (verb == CommandVerb.PUT && peekNextArg() == null) {
isValid = true;
@@ -211,6 +251,12 @@
case RESET:
DeviceConfig.resetToDefaults(resetMode, namespace);
break;
+ case SET_SYNC_DISABLED_FOR_TESTS:
+ DeviceConfig.setSyncDisabled(disableSyncMode);
+ break;
+ case IS_SYNC_DISABLED_FOR_TESTS:
+ pout.println(DeviceConfig.isSyncDisabled());
+ break;
default:
perr.println("Unspecified command");
return -1;
@@ -241,6 +287,16 @@
+ "trusted_defaults}");
pw.println(" NAMESPACE limits which flags are reset if provided, otherwise all "
+ "flags are reset");
+ pw.println(" set_sync_disabled_for_tests SYNC_DISABLED_MODE");
+ pw.println(" Modifies bulk property setting behavior for tests. When in one of the"
+ + " disabled modes this ensures that config isn't overwritten.");
+ pw.println(" SYNC_DISABLED_MODE is one of:");
+ pw.println(" none: Sync is not disabled. A reboot may be required to restart"
+ + " syncing.");
+ pw.println(" persistent: Sync is disabled, this state will survive a reboot.");
+ pw.println(" until_reboot: Sync is disabled until the next reboot.");
+ pw.println(" is_sync_disabled_for_tests");
+ pw.println(" Prints 'true' if sync is disabled, 'false' otherwise.");
}
private boolean delete(IContentProvider provider, String namespace, String key) {
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 3219b2b..bce576d 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -19,6 +19,12 @@
import static android.os.Process.ROOT_UID;
import static android.os.Process.SHELL_UID;
import static android.os.Process.SYSTEM_UID;
+import static android.provider.Settings.Config.SYNC_DISABLED_MODE_NONE;
+import static android.provider.Settings.Config.SYNC_DISABLED_MODE_PERSISTENT;
+import static android.provider.Settings.Config.SYNC_DISABLED_MODE_UNTIL_REBOOT;
+import static android.provider.Settings.SET_ALL_RESULT_DISABLED;
+import static android.provider.Settings.SET_ALL_RESULT_FAILURE;
+import static android.provider.Settings.SET_ALL_RESULT_SUCCESS;
import static android.provider.Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_MAGNIFICATION_CONTROLLER;
import static android.provider.Settings.Secure.NOTIFICATION_BUBBLES;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON_OVERLAY;
@@ -83,8 +89,10 @@
import android.os.UserManager;
import android.provider.DeviceConfig;
import android.provider.Settings;
+import android.provider.Settings.Config.SyncDisabledMode;
import android.provider.Settings.Global;
import android.provider.Settings.Secure;
+import android.provider.Settings.SetAllResult;
import android.provider.settings.validators.SystemSettingsValidators;
import android.provider.settings.validators.Validator;
import android.text.TextUtils;
@@ -338,6 +346,9 @@
// We have to call in the package manager with no lock held,
private volatile IPackageManager mPackageManager;
+ @GuardedBy("mLock")
+ private boolean mSyncConfigDisabledUntilReboot;
+
public static int makeKey(int type, int userId) {
return SettingsState.makeKey(type, userId);
}
@@ -446,11 +457,24 @@
String prefix = getSettingPrefix(args);
Map<String, String> flags = getSettingFlags(args);
Bundle result = new Bundle();
- result.putBoolean(Settings.KEY_CONFIG_SET_RETURN,
+ result.putInt(Settings.KEY_CONFIG_SET_ALL_RETURN,
setAllConfigSettings(prefix, flags));
return result;
}
+ case Settings.CALL_METHOD_SET_SYNC_DISABLED_CONFIG: {
+ final int mode = getSyncDisabledMode(args);
+ setSyncDisabledConfig(mode);
+ break;
+ }
+
+ case Settings.CALL_METHOD_IS_SYNC_DISABLED_CONFIG: {
+ Bundle result = new Bundle();
+ result.putBoolean(Settings.KEY_CONFIG_IS_SYNC_DISABLED_RETURN,
+ isSyncDisabledConfig());
+ return result;
+ }
+
case Settings.CALL_METHOD_RESET_CONFIG: {
final int mode = getResetModeEnforcingPermission(args);
String prefix = getSettingPrefix(args);
@@ -1105,7 +1129,8 @@
MUTATION_OPERATION_INSERT, 0);
}
- private boolean setAllConfigSettings(String prefix, Map<String, String> keyValues) {
+
+ private @SetAllResult int setAllConfigSettings(String prefix, Map<String, String> keyValues) {
if (DEBUG) {
Slog.v(LOG_TAG, "setAllConfigSettings for prefix: " + prefix);
}
@@ -1113,9 +1138,95 @@
enforceWritePermission(Manifest.permission.WRITE_DEVICE_CONFIG);
synchronized (mLock) {
+ if (isSyncDisabledConfigLocked()) {
+ return SET_ALL_RESULT_DISABLED;
+ }
final int key = makeKey(SETTINGS_TYPE_CONFIG, UserHandle.USER_SYSTEM);
- return mSettingsRegistry.setConfigSettingsLocked(key, prefix, keyValues,
+ boolean success = mSettingsRegistry.setConfigSettingsLocked(key, prefix, keyValues,
resolveCallingPackage());
+ return success ? SET_ALL_RESULT_SUCCESS : SET_ALL_RESULT_FAILURE;
+ }
+ }
+
+ private void setSyncDisabledConfig(@SyncDisabledMode int syncDisabledMode) {
+ if (DEBUG) {
+ Slog.v(LOG_TAG, "setSyncDisabledConfig(" + syncDisabledMode + ")");
+ }
+
+ enforceWritePermission(Manifest.permission.WRITE_DEVICE_CONFIG);
+
+ synchronized (mLock) {
+ setSyncDisabledConfigLocked(syncDisabledMode);
+ }
+ }
+
+ private boolean isSyncDisabledConfig() {
+ if (DEBUG) {
+ Slog.v(LOG_TAG, "isSyncDisabledConfig");
+ }
+
+ enforceWritePermission(Manifest.permission.WRITE_DEVICE_CONFIG);
+
+ synchronized (mLock) {
+ return isSyncDisabledConfigLocked();
+ }
+ }
+
+ @GuardedBy("mLock")
+ private void setSyncDisabledConfigLocked(@SyncDisabledMode int syncDisabledMode) {
+ boolean persistentValue;
+ boolean inMemoryValue;
+ if (syncDisabledMode == SYNC_DISABLED_MODE_NONE) {
+ persistentValue = false;
+ inMemoryValue = false;
+ } else if (syncDisabledMode == SYNC_DISABLED_MODE_PERSISTENT) {
+ persistentValue = true;
+ inMemoryValue = false;
+ } else if (syncDisabledMode == SYNC_DISABLED_MODE_UNTIL_REBOOT) {
+ persistentValue = false;
+ inMemoryValue = true;
+ } else {
+ throw new IllegalArgumentException(Integer.toString(syncDisabledMode));
+ }
+
+ mSyncConfigDisabledUntilReboot = inMemoryValue;
+
+ CallingIdentity callingIdentity = clearCallingIdentity();
+ try {
+ String globalSettingValue = persistentValue ? "1" : "0";
+ mSettingsRegistry.insertSettingLocked(SETTINGS_TYPE_GLOBAL,
+ UserHandle.USER_SYSTEM, Settings.Global.DEVICE_CONFIG_SYNC_DISABLED,
+ globalSettingValue, /*tag=*/null, /*makeDefault=*/false,
+ SettingsState.SYSTEM_PACKAGE_NAME, /*forceNotify=*/false,
+ /*criticalSettings=*/null, Settings.DEFAULT_OVERRIDEABLE_BY_RESTORE);
+ } finally {
+ restoreCallingIdentity(callingIdentity);
+ }
+ }
+
+ @GuardedBy("mLock")
+ private boolean isSyncDisabledConfigLocked() {
+ // Check the values used for both SYNC_DISABLED_MODE_PERSISTENT and
+ // SYNC_DISABLED_MODE_UNTIL_REBOOT.
+
+ // The SYNC_DISABLED_MODE_UNTIL_REBOOT value is cheap to check first.
+ if (mSyncConfigDisabledUntilReboot) {
+ return true;
+ }
+
+ // Now check the global setting used to implement SYNC_DISABLED_MODE_PERSISTENT.
+ CallingIdentity callingIdentity = clearCallingIdentity();
+ try {
+ Setting settingLocked = mSettingsRegistry.getSettingLocked(
+ SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM,
+ Global.DEVICE_CONFIG_SYNC_DISABLED);
+ if (settingLocked == null) {
+ return false;
+ }
+ String settingValue = settingLocked.getValue();
+ return settingValue != null && !"0".equals(settingValue);
+ } finally {
+ restoreCallingIdentity(callingIdentity);
}
}
@@ -2227,6 +2338,16 @@
return (args != null) && args.getBoolean(Settings.CALL_METHOD_OVERRIDEABLE_BY_RESTORE_KEY);
}
+ private static int getSyncDisabledMode(Bundle args) {
+ final int mode = (args != null)
+ ? args.getInt(Settings.CALL_METHOD_SYNC_DISABLED_MODE_KEY) : -1;
+ if (mode == SYNC_DISABLED_MODE_NONE || mode == SYNC_DISABLED_MODE_UNTIL_REBOOT
+ || mode == SYNC_DISABLED_MODE_PERSISTENT) {
+ return mode;
+ }
+ throw new IllegalArgumentException("Invalid sync disabled mode: " + mode);
+ }
+
private static int getResetModeEnforcingPermission(Bundle args) {
final int mode = (args != null) ? args.getInt(Settings.CALL_METHOD_RESET_MODE_KEY) : 0;
switch (mode) {
@@ -3426,7 +3547,7 @@
}
private final class UpgradeController {
- private static final int SETTINGS_VERSION = 202;
+ private static final int SETTINGS_VERSION = 203;
private final int mUserId;
@@ -5009,6 +5130,27 @@
currentVersion = 202;
}
+ if (currentVersion == 202) {
+ // Version 202: Power menu has been removed, and the privacy setting
+ // has been split into two for wallet and controls
+ final SettingsState secureSettings = getSecureSettingsLocked(userId);
+ final Setting showLockedContent = secureSettings.getSettingLocked(
+ Secure.POWER_MENU_LOCKED_SHOW_CONTENT);
+ if (!showLockedContent.isNull()) {
+ String currentValue = showLockedContent.getValue();
+
+ secureSettings.insertSettingOverrideableByRestoreLocked(
+ Secure.LOCKSCREEN_SHOW_CONTROLS,
+ currentValue, null /* tag */, false /* makeDefault */,
+ SettingsState.SYSTEM_PACKAGE_NAME);
+ secureSettings.insertSettingOverrideableByRestoreLocked(
+ Secure.LOCKSCREEN_SHOW_WALLET,
+ currentValue, null /* tag */, false /* makeDefault */,
+ SettingsState.SYSTEM_PACKAGE_NAME);
+ }
+ currentVersion = 203;
+ }
+
// vXXX: Add new settings above this point.
if (currentVersion != newVersion) {
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 1d321f2..6e256c1 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -455,8 +455,9 @@
<!-- Permission needed for CTS test - MatchContentFrameRateTest -->
<uses-permission android:name="android.permission.MODIFY_REFRESH_RATE_SWITCHING_TYPE" />
- <!-- Permission needed for CTS test - TimeManagerTest -->
+ <!-- Permissions needed for CTS test - TimeManagerTest -->
<uses-permission android:name="android.permission.MANAGE_TIME_AND_ZONE_DETECTION" />
+ <uses-permission android:name="android.permission.SUGGEST_EXTERNAL_TIME" />
<!-- Permission required for CTS test - android.server.biometrics -->
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
@@ -555,6 +556,9 @@
<!-- Permission required for CTS test - CtsAlarmManagerTestCases -->
<uses-permission android:name="android.permission.UPDATE_DEVICE_STATS" />
+ <!-- Permission required for CTS test - GlobalSearchSessionPlatformCtsTests -->
+ <uses-permission android:name="android.permission.READ_GLOBAL_APP_SEARCH_DATA" />
+
<application android:label="@string/app_label"
android:theme="@android:style/Theme.DeviceDefault.DayNight"
android:defaultToDeviceProtectedStorage="true"
diff --git a/packages/Shell/res/values-te/strings.xml b/packages/Shell/res/values-te/strings.xml
index 6050c1f..989b53e 100644
--- a/packages/Shell/res/values-te/strings.xml
+++ b/packages/Shell/res/values-te/strings.xml
@@ -43,5 +43,5 @@
<string name="bugreport_info_title" msgid="2306030793918239804">"బగ్ శీర్షిక"</string>
<string name="bugreport_info_description" msgid="5072835127481627722">"బగ్ సారాంశం"</string>
<string name="save" msgid="4781509040564835759">"సేవ్ చేయి"</string>
- <string name="bugreport_intent_chooser_title" msgid="7605709494790894076">"బగ్ నివేదిక భాగస్వామ్యం చేయండి"</string>
+ <string name="bugreport_intent_chooser_title" msgid="7605709494790894076">"బగ్ నివేదిక షేర్ చేయండి"</string>
</resources>
diff --git a/packages/Shell/src/com/android/shell/BugreportWarningActivity.java b/packages/Shell/src/com/android/shell/BugreportWarningActivity.java
index 2191d93..ecd1369 100644
--- a/packages/Shell/src/com/android/shell/BugreportWarningActivity.java
+++ b/packages/Shell/src/com/android/shell/BugreportWarningActivity.java
@@ -29,6 +29,7 @@
import android.os.Build;
import android.os.Bundle;
import android.view.LayoutInflater;
+import android.view.WindowManager;
import android.widget.CheckBox;
import com.android.internal.app.AlertActivity;
@@ -47,6 +48,10 @@
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
+ // Don't allow overlay windows.
+ getWindow().addSystemFlags(
+ WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
+
mSendIntent = getIntent().getParcelableExtra(Intent.EXTRA_INTENT);
// We need to touch the extras to unpack them so they get migrated to
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index d698975..8c092ae 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -588,13 +588,15 @@
android:label="@string/people_tile_title"
android:enabled="true"
android:exported="true"
+ android:windowDisablePreview="true"
android:theme="@style/Theme.PeopleTileConfigActivity">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/>
</intent-filter>
</activity>
- <activity android:name=".people.widget.LaunchConversationActivity" />
+ <activity android:name=".people.widget.LaunchConversationActivity"
+ android:windowDisablePreview="true" />
<!-- People Space Widget -->
<receiver
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/Interpolators.java b/packages/SystemUI/animation/src/com/android/systemui/animation/Interpolators.java
index 0a052df..044b5ed 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/Interpolators.java
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/Interpolators.java
@@ -16,6 +16,7 @@
package com.android.systemui.animation;
+import android.util.MathUtils;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.BounceInterpolator;
@@ -72,6 +73,27 @@
new PathInterpolator(0.9f, 0f, 0.7f, 1f);
/**
+ * Calculate the amount of overshoot using an exponential falloff function with desired
+ * properties, where the overshoot smoothly transitions at the 1.0f boundary into the
+ * overshoot, retaining its acceleration.
+ *
+ * @param progress a progress value going from 0 to 1
+ * @param overshootAmount the amount > 0 of overshoot desired. A value of 0.1 means the max
+ * value of the overall progress will be at 1.1.
+ * @param overshootStart the point in (0,1] where the result should reach 1
+ * @return the interpolated overshoot
+ */
+ public static float getOvershootInterpolation(float progress, float overshootAmount,
+ float overshootStart) {
+ if (overshootAmount == 0.0f || overshootStart == 0.0f) {
+ throw new IllegalArgumentException("Invalid values for overshoot");
+ }
+ float b = MathUtils.log((overshootAmount + 1) / (overshootAmount)) / overshootStart;
+ return MathUtils.max(0.0f,
+ (float) (1.0f - Math.exp(-b * progress)) * (overshootAmount + 1.0f));
+ }
+
+ /**
* Interpolate alpha for notifications background scrim during shade expansion.
* @param fraction Shade expansion fraction
*/
diff --git a/packages/SystemUI/plugin/bcsmartspace/src/com/android/systemui/plugins/BcSmartspaceDataPlugin.java b/packages/SystemUI/plugin/bcsmartspace/src/com/android/systemui/plugins/BcSmartspaceDataPlugin.java
index 32def03..b3c4374 100644
--- a/packages/SystemUI/plugin/bcsmartspace/src/com/android/systemui/plugins/BcSmartspaceDataPlugin.java
+++ b/packages/SystemUI/plugin/bcsmartspace/src/com/android/systemui/plugins/BcSmartspaceDataPlugin.java
@@ -19,6 +19,7 @@
import android.app.PendingIntent;
import android.app.smartspace.SmartspaceAction;
import android.app.smartspace.SmartspaceTarget;
+import android.app.smartspace.SmartspaceTargetEvent;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.Parcelable;
@@ -45,6 +46,18 @@
/** Unregister a listener. */
void unregisterListener(SmartspaceTargetListener listener);
+ /** Register a SmartspaceEventNotifier. */
+ default void registerSmartspaceEventNotifier(SmartspaceEventNotifier notifier) {}
+
+ /** Push a SmartspaceTargetEvent to the SmartspaceEventNotifier. */
+ default void notifySmartspaceEvent(SmartspaceTargetEvent event) {}
+
+ /** Allows for notifying the SmartspaceSession of SmartspaceTargetEvents. */
+ interface SmartspaceEventNotifier {
+ /** Pushes a given SmartspaceTargetEvent to the SmartspaceSession. */
+ void notifySmartspaceEvent(SmartspaceTargetEvent event);
+ }
+
/**
* Create a view to be shown within the parent. Do not add the view, as the parent
* will be responsible for correctly setting the LayoutParams
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QS.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QS.java
index 4d4c909..98ef9e2 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QS.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QS.java
@@ -33,7 +33,7 @@
String ACTION = "com.android.systemui.action.PLUGIN_QS";
- int VERSION = 8;
+ int VERSION = 9;
String TAG = "QS";
@@ -50,8 +50,13 @@
void setListening(boolean listening);
boolean isShowingDetail();
void closeDetail();
- default void setShowCollapsedOnKeyguard(boolean showCollapsedOnKeyguard) {}
- void animateHeaderSlidingIn(long delay);
+
+ /**
+ * Set that we're currently pulse expanding
+ *
+ * @param pulseExpanding if we're currently expanding during pulsing
+ */
+ default void setPulseExpanding(boolean pulseExpanding) {}
void animateHeaderSlidingOut();
void setQsExpansion(float qsExpansionFraction, float headerTranslation);
void setHeaderListening(boolean listening);
@@ -79,10 +84,23 @@
void setTranslateWhileExpanding(boolean shouldTranslate);
/**
+ * Set the amount of pixels we have currently dragged down if we're transitioning to the full
+ * shade. 0.0f means we're not transitioning yet.
+ */
+ default void setTransitionToFullShadeAmount(float pxAmount, boolean animated) {}
+
+ /**
* A rounded corner clipping that makes QS feel as if it were behind everything.
*/
void setFancyClipping(int top, int bottom, int cornerRadius, boolean visible);
+ /**
+ * @return if quick settings is fully collapsed currently
+ */
+ default boolean isFullyCollapsed() {
+ return true;
+ }
+
@ProvidesInterface(version = HeightListener.VERSION)
interface HeightListener {
int VERSION = 1;
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
index 7c5459c1..35eebac 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
@@ -81,5 +81,6 @@
android:layout_height="@dimen/notification_shelf_height"
android:layout_below="@id/keyguard_status_area"
android:paddingStart="@dimen/below_clock_padding_start_extra"
+ android:visibility="invisible"
/>
</com.android.keyguard.KeyguardClockSwitch>
diff --git a/packages/SystemUI/res-keyguard/values-eu/strings.xml b/packages/SystemUI/res-keyguard/values-eu/strings.xml
index 9f00e66..83a0a32 100644
--- a/packages/SystemUI/res-keyguard/values-eu/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-eu/strings.xml
@@ -24,7 +24,7 @@
<string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"Idatzi PIN kodea"</string>
<string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"Idatzi SIM txartelaren PUK kodea eta PIN kode berria"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"SIM txartelaren PUK kodea"</string>
- <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"SIM txartelaren PIN kode berria"</string>
+ <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"SIM txartelaren PIN berria"</string>
<string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Pasahitza idazteko, sakatu hau"</font></string>
<string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Idatzi desblokeatzeko pasahitza"</string>
<string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Idatzi desblokeatzeko PIN kodea"</string>
@@ -63,7 +63,7 @@
<string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Eredua ahaztu zaizu"</string>
<string name="kg_wrong_pattern" msgid="5907301342430102842">"Eredua ez da zuzena"</string>
<string name="kg_wrong_password" msgid="4143127991071670512">"Pasahitza ez da zuzena"</string>
- <string name="kg_wrong_pin" msgid="4160978845968732624">"PIN kode hori ez da zuzena"</string>
+ <string name="kg_wrong_pin" msgid="4160978845968732624">"PIN hori ez da zuzena"</string>
<plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="991400408675793914">
<item quantity="other">Saiatu berriro <xliff:g id="NUMBER">%d</xliff:g> segundo igarotakoan.</item>
<item quantity="one">Saiatu berriro segundo bat igarotakoan.</item>
diff --git a/packages/SystemUI/res/drawable/circle_green_10dp.xml b/packages/SystemUI/res/color/media_player_solid_button_bg.xml
similarity index 68%
copy from packages/SystemUI/res/drawable/circle_green_10dp.xml
copy to packages/SystemUI/res/color/media_player_solid_button_bg.xml
index 571ec62..96685ab 100644
--- a/packages/SystemUI/res/drawable/circle_green_10dp.xml
+++ b/packages/SystemUI/res/color/media_player_solid_button_bg.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- ~ Copyright (C) 2020 The Android Open Source Project
+ ~ Copyright (C) 2021 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
@@ -14,9 +14,8 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size android:height="10dp"
- android:width="10dp" />
- <solid android:color="#34A853" />
-</shape>
\ No newline at end of file
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
+ <item android:color="?androidprv:attr/colorAccentTertiary"/>
+</selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/circle_green_10dp.xml b/packages/SystemUI/res/drawable/availability_dot_10dp.xml
similarity index 75%
rename from packages/SystemUI/res/drawable/circle_green_10dp.xml
rename to packages/SystemUI/res/drawable/availability_dot_10dp.xml
index 571ec62..ab40eb0 100644
--- a/packages/SystemUI/res/drawable/circle_green_10dp.xml
+++ b/packages/SystemUI/res/drawable/availability_dot_10dp.xml
@@ -15,8 +15,10 @@
~ limitations under the License.
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size android:height="10dp"
- android:width="10dp" />
- <solid android:color="#34A853" />
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ android:shape="oval">
+ <size
+ android:height="10dp"
+ android:width="10dp" />
+ <solid android:color="?androidprv:attr/colorAccentPrimaryVariant" />
</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/brightness_progress_full_drawable.xml b/packages/SystemUI/res/drawable/brightness_progress_full_drawable.xml
index ceef9f9..4d9188c 100644
--- a/packages/SystemUI/res/drawable/brightness_progress_full_drawable.xml
+++ b/packages/SystemUI/res/drawable/brightness_progress_full_drawable.xml
@@ -34,7 +34,7 @@
android:right="@dimen/rounded_slider_icon_inset">
<com.android.systemui.util.AlphaTintDrawableWrapper
android:drawable="@drawable/ic_brightness"
- android:tint="?android:attr/colorBackground"
- android:alpha="0.8"/>
+ android:tint="?android:attr/textColorPrimaryInverse"
+ />
</item>
</layer-list>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/people_space_messages_count_background.xml b/packages/SystemUI/res/drawable/people_space_messages_count_background.xml
index 0fc112e..97752d0 100644
--- a/packages/SystemUI/res/drawable/people_space_messages_count_background.xml
+++ b/packages/SystemUI/res/drawable/people_space_messages_count_background.xml
@@ -14,7 +14,8 @@
~ 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="#9ED582" />
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
+ <solid android:color="?androidprv:attr/colorAccentPrimary" />
<corners android:radius="@dimen/people_space_messages_count_radius" />
</shape>
diff --git a/packages/SystemUI/res/drawable/qs_footer_action_chip_background.xml b/packages/SystemUI/res/drawable/qs_footer_action_chip_background.xml
index 77b9871..a45769f 100644
--- a/packages/SystemUI/res/drawable/qs_footer_action_chip_background.xml
+++ b/packages/SystemUI/res/drawable/qs_footer_action_chip_background.xml
@@ -34,7 +34,7 @@
</item>
<item>
<shape android:shape="rectangle">
- <stroke android:width="1dp" android:color="@color/qs_footer_action_border"/>
+ <stroke android:width="1dp" android:color="?android:attr/colorBackground"/>
<corners android:radius="@dimen/qs_footer_action_corner_radius"/>
</shape>
</item>
diff --git a/packages/SystemUI/res/layout-land/global_screenshot_preview.xml b/packages/SystemUI/res/layout-land/global_screenshot_preview.xml
deleted file mode 100644
index 93664da..0000000
--- a/packages/SystemUI/res/layout-land/global_screenshot_preview.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ 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.
- -->
-<ImageView
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- android:id="@+id/global_screenshot_preview"
- android:layout_width="wrap_content"
- android:layout_height="@dimen/global_screenshot_x_scale"
- android:layout_gravity="center"
- android:layout_marginStart="@dimen/screenshot_offset_x"
- android:layout_marginBottom="@dimen/screenshot_offset_y"
- android:scaleType="fitStart"
- android:elevation="@dimen/screenshot_preview_elevation"
- android:visibility="invisible"
- android:background="@drawable/screenshot_rounded_corners"
- android:adjustViewBounds="true"
- android:contentDescription="@string/screenshot_edit_label"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintStart_toStartOf="parent"/>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/controls_onboarding.xml b/packages/SystemUI/res/layout/controls_onboarding.xml
index 577a3b4..d234c32 100644
--- a/packages/SystemUI/res/layout/controls_onboarding.xml
+++ b/packages/SystemUI/res/layout/controls_onboarding.xml
@@ -46,7 +46,7 @@
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_gravity="center_vertical"
- android:textColor="?attr/wallpaperTextColor"
+ android:textColor="?android:attr/colorPrimary"
android:textSize="16sp"/>
<ImageView
android:id="@+id/dismiss"
@@ -58,7 +58,7 @@
android:layout_marginEnd="2dp"
android:alpha="0.7"
android:src="@drawable/ic_close_white"
- android:tint="?attr/wallpaperTextColor"
+ android:tint="?android:attr/colorPrimary"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/accessibility_desc_close"/>
</LinearLayout>
diff --git a/packages/SystemUI/res/layout/keyguard_bottom_area.xml b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
index 95483f1..0dc1473 100644
--- a/packages/SystemUI/res/layout/keyguard_bottom_area.xml
+++ b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
@@ -21,8 +21,7 @@
android:id="@+id/keyguard_bottom_area"
android:layout_height="match_parent"
android:layout_width="match_parent"
- android:outlineProvider="none"
- android:elevation="5dp" > <!-- Put it above the status bar header -->
+ android:outlineProvider="none" > <!-- Put it above the status bar header -->
<LinearLayout
android:id="@+id/keyguard_indication_area"
@@ -58,12 +57,6 @@
</LinearLayout>
- <FrameLayout
- android:id="@+id/preview_container"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
- </FrameLayout>
-
<com.android.systemui.statusbar.KeyguardAffordanceView
android:id="@+id/camera_button"
android:layout_height="@dimen/keyguard_affordance_height"
diff --git a/packages/SystemUI/res/layout/media_smartspace_recommendations.xml b/packages/SystemUI/res/layout/media_smartspace_recommendations.xml
index 9e67258..8c54e2c 100644
--- a/packages/SystemUI/res/layout/media_smartspace_recommendations.xml
+++ b/packages/SystemUI/res/layout/media_smartspace_recommendations.xml
@@ -75,7 +75,7 @@
android:id="@+id/media_logo1"
android:layout_width="@dimen/qs_media_icon_size"
android:layout_height="@dimen/qs_media_icon_size"
- style="@style/MediaPlayer.AppIcon.Recommendation" />
+ style="@style/MediaPlayer.AppIcon" />
<ImageView
android:id="@+id/media_cover2"
@@ -91,7 +91,7 @@
android:id="@+id/media_logo2"
android:layout_width="@dimen/qs_media_icon_size"
android:layout_height="@dimen/qs_media_icon_size"
- style="@style/MediaPlayer.AppIcon.Recommendation" />
+ style="@style/MediaPlayer.AppIcon" />
<ImageView
android:id="@+id/media_cover3"
@@ -107,7 +107,7 @@
android:id="@+id/media_logo3"
android:layout_width="@dimen/qs_media_icon_size"
android:layout_height="@dimen/qs_media_icon_size"
- style="@style/MediaPlayer.AppIcon.Recommendation" />
+ style="@style/MediaPlayer.AppIcon" />
<ImageView
android:id="@+id/media_cover4"
@@ -123,7 +123,7 @@
android:id="@+id/media_logo4"
android:layout_width="@dimen/qs_media_icon_size"
android:layout_height="@dimen/qs_media_icon_size"
- style="@style/MediaPlayer.AppIcon.Recommendation" />
+ style="@style/MediaPlayer.AppIcon" />
<ImageView
android:id="@+id/media_cover5"
@@ -139,7 +139,7 @@
android:id="@+id/media_logo5"
android:layout_width="@dimen/qs_media_icon_size"
android:layout_height="@dimen/qs_media_icon_size"
- style="@style/MediaPlayer.AppIcon.Recommendation" />
+ style="@style/MediaPlayer.AppIcon" />
<ImageView
android:id="@+id/media_cover6"
@@ -155,7 +155,7 @@
android:id="@+id/media_logo6"
android:layout_width="@dimen/qs_media_icon_size"
android:layout_height="@dimen/qs_media_icon_size"
- style="@style/MediaPlayer.AppIcon.Recommendation" />
+ style="@style/MediaPlayer.AppIcon" />
<!-- Long press menu -->
<TextView
diff --git a/packages/SystemUI/res/layout/media_view.xml b/packages/SystemUI/res/layout/media_view.xml
index 8dbbd4a..e999872 100644
--- a/packages/SystemUI/res/layout/media_view.xml
+++ b/packages/SystemUI/res/layout/media_view.xml
@@ -145,6 +145,7 @@
android:layout_width="@dimen/qs_seamless_icon_size"
android:layout_height="@dimen/qs_seamless_icon_size"
android:layout_gravity="center"
+ android:tint="?android:attr/textColorPrimary"
android:src="@*android:drawable/ic_media_seamless" />
<TextView
android:id="@+id/media_seamless_text"
diff --git a/packages/SystemUI/res/layout/ongoing_call_chip.xml b/packages/SystemUI/res/layout/ongoing_call_chip.xml
index 90214b7..f8175d4 100644
--- a/packages/SystemUI/res/layout/ongoing_call_chip.xml
+++ b/packages/SystemUI/res/layout/ongoing_call_chip.xml
@@ -13,37 +13,45 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<LinearLayout
+<!-- Have the wrapper frame layout match the parent height so that we get a larger touch area for
+ the chip. -->
+<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ongoing_call_chip"
android:layout_width="wrap_content"
- android:layout_height="@dimen/ongoing_appops_chip_height"
+ android:layout_height="match_parent"
android:layout_gravity="center_vertical|start"
- android:gravity="center_vertical"
- android:background="@drawable/ongoing_call_chip_bg"
- android:paddingStart="@dimen/ongoing_call_chip_side_padding"
- android:paddingEnd="@dimen/ongoing_call_chip_side_padding"
- android:contentDescription="@string/ongoing_phone_call_content_description"
>
-
- <ImageView
- android:src="@*android:drawable/ic_phone"
- android:layout_width="@dimen/ongoing_call_chip_icon_size"
- android:layout_height="@dimen/ongoing_call_chip_icon_size"
- android:tint="?android:attr/colorPrimary"
- />
-
- <!-- TODO(b/183229367): The text in this view isn't quite centered within the chip. -->
- <com.android.systemui.statusbar.phone.ongoingcall.OngoingCallChronometer
- android:id="@+id/ongoing_call_chip_time"
+ <LinearLayout
android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:singleLine="true"
- android:gravity="center|start"
- android:paddingStart="@dimen/ongoing_call_chip_icon_text_padding"
- android:textAppearance="@android:style/TextAppearance.Material.Small"
- android:fontFamily="@*android:string/config_headlineFontFamily"
- android:textColor="?android:attr/colorPrimary"
- />
+ android:layout_height="@dimen/ongoing_appops_chip_height"
+ android:layout_gravity="center_vertical"
+ android:gravity="center"
+ android:background="@drawable/ongoing_call_chip_bg"
+ android:paddingStart="@dimen/ongoing_call_chip_side_padding"
+ android:paddingEnd="@dimen/ongoing_call_chip_side_padding"
+ android:contentDescription="@string/ongoing_phone_call_content_description"
+ android:minWidth="@dimen/min_clickable_item_size"
+ >
-</LinearLayout>
+ <ImageView
+ android:src="@*android:drawable/ic_phone"
+ android:layout_width="@dimen/ongoing_call_chip_icon_size"
+ android:layout_height="@dimen/ongoing_call_chip_icon_size"
+ android:tint="?android:attr/colorPrimary"
+ />
+
+ <com.android.systemui.statusbar.phone.ongoingcall.OngoingCallChronometer
+ android:id="@+id/ongoing_call_chip_time"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:gravity="center|start"
+ android:paddingStart="@dimen/ongoing_call_chip_icon_text_padding"
+ android:textAppearance="@android:style/TextAppearance.Material.Small"
+ android:fontFamily="@*android:string/config_headlineFontFamily"
+ android:textColor="?android:attr/colorPrimary"
+ />
+
+ </LinearLayout>
+</FrameLayout>
diff --git a/packages/SystemUI/res/layout/people_tile_large_empty.xml b/packages/SystemUI/res/layout/people_tile_large_empty.xml
index 69e2770..2c6acbc 100644
--- a/packages/SystemUI/res/layout/people_tile_large_empty.xml
+++ b/packages/SystemUI/res/layout/people_tile_large_empty.xml
@@ -14,30 +14,28 @@
~ limitations under the License.
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/item"
+ android:background="@drawable/people_space_tile_view_card"
android:theme="@android:style/Theme.DeviceDefault.DayNight"
android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="match_parent"
+ android:paddingHorizontal="16dp"
+ android:paddingTop="14dp"
+ android:paddingBottom="16dp">
<LinearLayout
- android:id="@+id/item"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_gravity="center"
- android:gravity="center"
- android:background="@drawable/people_space_tile_view_card"
- android:orientation="vertical"
- android:paddingHorizontal="16dp"
- android:paddingVertical="16dp">
+ android:layout_height="wrap_content"
+ android:gravity="top|center_horizontal"
+ android:orientation="vertical">
<ImageView
android:id="@+id/person_icon"
- android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/name"
- android:layout_gravity="center"
android:paddingTop="14dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -45,24 +43,22 @@
android:singleLine="true"
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
android:textColor="?android:attr/textColorPrimary"
- android:textSize="16sp" />
+ android:textSize="@dimen/name_text_size_for_large" />
<TextView
android:id="@+id/last_interaction"
- android:layout_gravity="center"
android:text="@string/empty_status"
android:textColor="?android:attr/textColorSecondary"
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
- android:textSize="14sp"
+ android:textSize="@dimen/content_text_size_for_large"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:singleLine="true"/>
- <ImageView
- android:id="@+id/availability"
- android:layout_gravity="center"
- android:layout_width="10dp"
- android:layout_height="26dp"
- android:paddingTop="16dp"
- android:background="@drawable/circle_green_10dp"/>
</LinearLayout>
+ <ImageView
+ android:id="@+id/availability"
+ android:layout_gravity="bottom|center_horizontal"
+ android:layout_width="10dp"
+ android:layout_height="10dp"
+ android:background="@drawable/availability_dot_10dp"/>
</FrameLayout>
\ No newline at end of file
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 b77670e..4994c69 100644
--- a/packages/SystemUI/res/layout/people_tile_large_with_content.xml
+++ b/packages/SystemUI/res/layout/people_tile_large_with_content.xml
@@ -13,147 +13,136 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:background="@drawable/people_space_tile_view_card"
- android:id="@+id/item"
- android:clipToOutline="true"
- android:theme="@android:style/Theme.DeviceDefault.DayNight"
- android:layout_gravity="center"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="match_parent"
+ android:layout_gravity="center"
+ android:padding="16dp"
+ android:orientation="vertical">
- <include layout="@layout/people_status_scrim_layout" />
-
- <LinearLayout
+ <RelativeLayout
android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_gravity="center"
- android:padding="16dp"
- android:orientation="vertical">
+ android:layout_height="wrap_content"
+ android:gravity="start|top">
- <RelativeLayout
- android:layout_width="match_parent"
+ <LinearLayout
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:gravity="start|top">
+ android:layout_alignParentStart="true"
+ android:gravity="start|top"
+ android:orientation="horizontal">
- <LinearLayout
+ <ImageView
+ android:id="@+id/person_icon"
+ android:layout_marginStart="-2dp"
+ android:layout_marginTop="-2dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_alignParentStart="true"
- android:gravity="start|top"
+ android:layout_weight="1" />
+
+ <ImageView
+ android:id="@+id/availability"
+ android:layout_marginStart="-2dp"
+ android:layout_width="10dp"
+ android:layout_height="10dp"
+ android:background="@drawable/availability_dot_10dp" />
+ </LinearLayout>
+
+ <TextView
+ android:id="@+id/messages_count"
+ android:layout_alignParentEnd="true"
+ android:paddingStart="8dp"
+ android:paddingEnd="8dp"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+ android:textColor="?android:attr/textColorPrimary"
+ android:background="@drawable/people_space_messages_count_background"
+ android:textSize="14sp"
+ android:maxLines="1"
+ android:ellipsize="end"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:visibility="gone" />
+ </RelativeLayout>
+
+ <RelativeLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <include layout="@layout/people_tile_punctuation_background_large" />
+
+ <include layout="@layout/people_tile_emoji_background_large" />
+
+ <TextView
+ android:layout_gravity="top"
+ android:id="@+id/name"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingBottom="@dimen/below_name_text_padding"
+ android:gravity="start|top"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:text="@string/empty_user_name"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+ android:textColor="?android:attr/textColorPrimary"
+ android:textSize="@dimen/name_text_size_for_content" />
+
+ <LinearLayout
+ android:id="@+id/content"
+ android:layout_below="@id/name"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <LinearLayout
+ android:id="@+id/status_icon_and_label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingBottom="4dp"
+ android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
- android:id="@+id/person_icon"
- android:layout_marginStart="-2dp"
- android:layout_marginTop="-2dp"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_weight="1" />
-
- <ImageView
- android:id="@+id/availability"
- android:layout_marginStart="-2dp"
- android:layout_width="10dp"
- android:layout_height="10dp"
- android:background="@drawable/circle_green_10dp" />
- </LinearLayout>
-
- <TextView
- android:id="@+id/messages_count"
- android:layout_alignParentEnd="true"
- android:paddingStart="8dp"
- android:paddingEnd="8dp"
- android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
- android:textColor="?android:attr/textColorPrimary"
- android:background="@drawable/people_space_messages_count_background"
- android:textSize="14sp"
- android:maxLines="1"
- android:ellipsize="end"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:visibility="gone" />
- </RelativeLayout>
-
- <RelativeLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <include layout="@layout/people_tile_punctuation_background_large" />
-
- <include layout="@layout/people_tile_emoji_background_large" />
-
- <LinearLayout
- android:id="@+id/content"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
+ android:id="@+id/predefined_icon"
+ android:tint="?android:attr/colorAccent"
+ android:gravity="start|center_vertical"
+ android:layout_width="@dimen/regular_predefined_icon"
+ android:layout_height="@dimen/regular_predefined_icon" />
<TextView
android:layout_gravity="center"
- android:id="@+id/name"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingBottom="12dp"
- android:gravity="start"
- android:singleLine="true"
- android:ellipsize="end"
- android:text="@string/empty_user_name"
- android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
- android:textColor="?android:attr/textColorPrimary"
- android:textSize="14sp" />
-
- <LinearLayout
- android:id="@+id/status_icon_and_label"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
+ android:id="@+id/subtext"
android:paddingBottom="4dp"
android:gravity="center_vertical"
- android:orientation="horizontal">
-
- <ImageView
- android:id="@+id/predefined_icon"
- android:tint="?android:attr/colorAccent"
- android:gravity="start|center_vertical"
- android:paddingEnd="6dp"
- android:layout_width="24dp"
- android:layout_height="18dp" />
-
- <TextView
- android:layout_gravity="center"
- android:id="@+id/subtext"
- android:gravity="center_vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:ellipsize="end"
- android:singleLine="true"
- android:text="@string/empty_user_name"
- android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
- android:textColor="?android:attr/textColorSecondary"
- android:textSize="12sp" />
- </LinearLayout>
-
- <ImageView
- android:id="@+id/image"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="@drawable/people_space_content_background"
- android:gravity="center"
- android:scaleType="centerCrop" />
-
- <TextView
- android:layout_gravity="center"
- android:id="@+id/text_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
- android:maxLines="2"
- android:singleLine="false"
- android:text="@string/empty_status"
+ android:singleLine="true"
+ android:text="@string/empty_user_name"
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
- android:textColor="?android:attr/textColorPrimary"
- android:textSize="@dimen/content_text_size_for_large" />
+ android:textColor="?android:attr/textColorSecondary"
+ android:textSize="12sp" />
</LinearLayout>
- </RelativeLayout>
- </LinearLayout>
-</RelativeLayout>
\ No newline at end of file
+
+ <ImageView
+ android:id="@+id/image"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@drawable/people_space_content_background"
+ android:gravity="center"
+ android:scaleType="centerCrop" />
+
+ <TextView
+ android:layout_gravity="center"
+ android:id="@+id/text_content"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:ellipsize="end"
+ android:maxLines="2"
+ android:singleLine="false"
+ android:text="@string/empty_status"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+ android:textColor="?android:attr/textColorPrimary"
+ android:textSize="@dimen/content_text_size_for_large" />
+ </LinearLayout>
+ </RelativeLayout>
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/people_tile_large_with_notification_content.xml b/packages/SystemUI/res/layout/people_tile_large_with_notification_content.xml
new file mode 100644
index 0000000..60ff68e
--- /dev/null
+++ b/packages/SystemUI/res/layout/people_tile_large_with_notification_content.xml
@@ -0,0 +1,26 @@
+<?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.
+ -->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:background="@drawable/people_space_tile_view_card"
+ android:id="@+id/item"
+ android:clipToOutline="true"
+ android:theme="@android:style/Theme.DeviceDefault.DayNight"
+ android:layout_gravity="center"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <include layout="@layout/people_tile_large_with_content" />
+</RelativeLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/people_tile_large_with_status_content.xml b/packages/SystemUI/res/layout/people_tile_large_with_status_content.xml
new file mode 100644
index 0000000..cbc6ea8
--- /dev/null
+++ b/packages/SystemUI/res/layout/people_tile_large_with_status_content.xml
@@ -0,0 +1,27 @@
+<?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.
+ -->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:background="@drawable/people_space_tile_view_card"
+ android:id="@+id/item"
+ android:clipToOutline="true"
+ android:theme="@android:style/Theme.DeviceDefault.DayNight"
+ android:layout_gravity="center"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <include layout="@layout/people_status_scrim_layout" />
+ <include layout="@layout/people_tile_large_with_content" />
+</RelativeLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/people_tile_medium_empty.xml b/packages/SystemUI/res/layout/people_tile_medium_empty.xml
index 4236493..bebc872 100644
--- a/packages/SystemUI/res/layout/people_tile_medium_empty.xml
+++ b/packages/SystemUI/res/layout/people_tile_medium_empty.xml
@@ -35,13 +35,14 @@
android:layout_height="64dp" />
<ImageView
android:id="@+id/availability"
+ android:gravity="top"
android:layout_marginStart="-2dp"
android:layout_width="10dp"
android:layout_height="10dp"
- android:background="@drawable/circle_green_10dp" />
+ android:background="@drawable/availability_dot_10dp" />
<LinearLayout
android:orientation="vertical"
- android:paddingStart="6dp"
+ android:paddingStart="4dp"
android:gravity="top"
android:layout_width="match_parent"
android:layout_height="wrap_content">
@@ -50,7 +51,7 @@
android:text="@string/empty_user_name"
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
android:textColor="?android:attr/textColorPrimary"
- android:textSize="14sp"
+ android:textSize="@dimen/empty_name_text_size_for_medium"
android:maxLines="1"
android:ellipsize="end"
android:layout_width="wrap_content"
@@ -60,7 +61,7 @@
android:text="@string/empty_status"
android:textColor="?android:attr/textColorSecondary"
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
- android:textSize="12sp"
+ android:textSize="@dimen/content_text_size_for_medium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="3"
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 8df0bf8..a7a6354 100644
--- a/packages/SystemUI/res/layout/people_tile_medium_with_content.xml
+++ b/packages/SystemUI/res/layout/people_tile_medium_with_content.xml
@@ -57,12 +57,14 @@
android:layout_marginStart="-2dp"
android:layout_width="10dp"
android:layout_height="10dp"
- android:background="@drawable/circle_green_10dp" />
+ android:background="@drawable/availability_dot_10dp" />
<LinearLayout
+ android:id="@+id/medium_content"
android:orientation="vertical"
android:gravity="top|start"
android:paddingStart="12dp"
+ android:paddingBottom="@dimen/medium_content_padding_above_name"
android:layout_width="match_parent"
android:layout_height="wrap_content">
@@ -72,7 +74,7 @@
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
android:textColor="?android:attr/textColorSecondary"
android:textSize="12sp"
- android:paddingBottom="4dp"
+ android:paddingBottom="8dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
@@ -104,9 +106,9 @@
android:gravity="bottom"
android:layout_gravity="center_vertical"
android:orientation="horizontal"
- android:paddingTop="2dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:minHeight="18dp"
android:clipToOutline="true">
<TextView
android:id="@+id/name"
@@ -115,9 +117,10 @@
android:text="@string/empty_user_name"
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
android:textColor="?android:attr/textColorPrimary"
- android:textSize="14sp"
+ android:textSize="@dimen/name_text_size_for_content"
android:singleLine="true"
android:ellipsize="end"
+ android:paddingEnd="8dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
@@ -139,9 +142,8 @@
android:id="@+id/predefined_icon"
android:tint="?android:attr/colorAccent"
android:gravity="end|center_vertical"
- android:paddingStart="6dp"
- android:layout_width="24dp"
- android:layout_height="18dp" />
+ android:layout_width="@dimen/regular_predefined_icon"
+ android:layout_height="@dimen/regular_predefined_icon" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>
diff --git a/packages/SystemUI/res/layout/people_tile_small.xml b/packages/SystemUI/res/layout/people_tile_small.xml
index 7c28fc1..4e5c04c 100644
--- a/packages/SystemUI/res/layout/people_tile_small.xml
+++ b/packages/SystemUI/res/layout/people_tile_small.xml
@@ -48,12 +48,11 @@
android:id="@+id/messages_count"
android:layout_gravity="center"
android:gravity="center"
- android:paddingStart="8dp"
- android:paddingEnd="8dp"
+ android:paddingHorizontal="8dp"
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
android:textColor="?android:attr/textColorPrimary"
android:background="@drawable/people_space_messages_count_background"
- android:textSize="14sp"
+ android:textSize="@dimen/name_text_size_for_small"
android:maxLines="1"
android:ellipsize="end"
android:layout_width="wrap_content"
@@ -71,6 +70,6 @@
android:paddingHorizontal="4dp"
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
android:textColor="?android:attr/textColorPrimary"
- android:textSize="14sp" />
+ android:textSize="@dimen/name_text_size_for_small" />
</LinearLayout>
</FrameLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/qs_carrier.xml b/packages/SystemUI/res/layout/qs_carrier.xml
index c521dc2..d4594d1 100644
--- a/packages/SystemUI/res/layout/qs_carrier.xml
+++ b/packages/SystemUI/res/layout/qs_carrier.xml
@@ -33,7 +33,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
- android:textAppearance="@style/TextAppearance.QS.Status"
+ android:textAppearance="@style/TextAppearance.QS.Status.Carriers"
android:textDirection="locale"
android:marqueeRepeatLimit="marquee_forever"
android:singleLine="true"
diff --git a/packages/SystemUI/res/layout/qs_carrier_group.xml b/packages/SystemUI/res/layout/qs_carrier_group.xml
index 810c959..6e13ab9 100644
--- a/packages/SystemUI/res/layout/qs_carrier_group.xml
+++ b/packages/SystemUI/res/layout/qs_carrier_group.xml
@@ -32,7 +32,7 @@
android:minWidth="48dp"
android:minHeight="48dp"
android:gravity="center_vertical"
- android:textAppearance="@style/TextAppearance.QS.Status.NoCarrierText"
+ android:textAppearance="@style/TextAppearance.QS.Status.Carriers.NoCarrierText"
android:textDirection="locale"
android:marqueeRepeatLimit="marquee_forever"
android:singleLine="true"
diff --git a/packages/SystemUI/res/layout/qs_customize_divider.xml b/packages/SystemUI/res/layout/qs_customize_divider.xml
index 035f493..b4e3010 100644
--- a/packages/SystemUI/res/layout/qs_customize_divider.xml
+++ b/packages/SystemUI/res/layout/qs_customize_divider.xml
@@ -24,5 +24,5 @@
android:gravity="center"
android:paddingTop="24dp"
android:paddingBottom="24dp"
- android:textAppearance="@style/TextAppearance.QSEdit.Headers"
+ android:textAppearance="@style/TextAppearance.QSEdit"
android:text="@string/drag_to_add_tiles" />
diff --git a/packages/SystemUI/res/layout/qs_customize_header.xml b/packages/SystemUI/res/layout/qs_customize_header.xml
index 481561d..626d53a 100644
--- a/packages/SystemUI/res/layout/qs_customize_header.xml
+++ b/packages/SystemUI/res/layout/qs_customize_header.xml
@@ -22,5 +22,5 @@
android:layout_height="wrap_content"
android:gravity="center"
android:minHeight="@dimen/qs_customize_header_min_height"
- android:textAppearance="@style/TextAppearance.QSEdit.Headers"
+ android:textAppearance="@style/TextAppearance.QSEdit"
android:text="@string/drag_to_rearrange_tiles" />
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/qs_footer_impl.xml b/packages/SystemUI/res/layout/qs_footer_impl.xml
index 266ecef..0a9feb8 100644
--- a/packages/SystemUI/res/layout/qs_footer_impl.xml
+++ b/packages/SystemUI/res/layout/qs_footer_impl.xml
@@ -51,7 +51,7 @@
android:focusable="true"
android:gravity="center_vertical"
android:singleLine="true"
- android:textAppearance="@style/TextAppearance.QS.Build"
+ android:textAppearance="@style/TextAppearance.QS.Status.Build"
android:visibility="gone" />
<com.android.systemui.qs.PageIndicator
@@ -87,7 +87,7 @@
android:focusable="true"
android:padding="@dimen/qs_footer_icon_padding"
android:src="@*android:drawable/ic_mode_edit"
- android:tint="?android:attr/colorForeground" />
+ android:tint="?android:attr/textColorPrimary" />
<com.android.systemui.statusbar.phone.MultiUserSwitch
android:id="@+id/multi_user_switch"
@@ -126,7 +126,7 @@
android:padding="@dimen/qs_footer_icon_padding"
android:scaleType="centerInside"
android:src="@drawable/ic_settings"
- android:tint="?android:attr/colorForeground" />
+ android:tint="?android:attr/textColorPrimary" />
<com.android.systemui.statusbar.AlphaOptimizedImageView
android:id="@+id/tuner_icon"
@@ -152,7 +152,7 @@
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/colorForeground" />
+ android:tint="?android:attr/textColorPrimary" />
</LinearLayout>
</LinearLayout>
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index f4cb3b1..3543fd1 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -37,6 +37,25 @@
android:layout_height="match_parent"
android:layout_width="match_parent" />
+ <include
+ layout="@layout/keyguard_bottom_area"
+ android:visibility="gone" />
+
+ <ViewStub
+ android:id="@+id/keyguard_user_switcher_stub"
+ android:layout="@layout/keyguard_user_switcher"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent" />
+
+ <include layout="@layout/status_bar_expanded_plugin_frame"/>
+
+ <include layout="@layout/dock_info_bottom_area_overlay" />
+
+ <com.android.keyguard.LockIconView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/lock_icon_view" />
+
<com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -49,6 +68,18 @@
layout="@layout/keyguard_status_view"
android:visibility="gone"/>
+ <com.android.systemui.scrim.ScrimView
+ android:id="@+id/scrim_notifications"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:importantForAccessibility="no"
+ systemui:ignoreRightInset="true"
+ systemui:layout_constraintStart_toStartOf="parent"
+ systemui:layout_constraintEnd_toEndOf="parent"
+ systemui:layout_constraintTop_toTopOf="parent"
+ systemui:layout_constraintBottom_toBottomOf="parent"
+ />
+
<include layout="@layout/dock_info_overlay" />
<FrameLayout
@@ -101,22 +132,9 @@
</com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer>
- <include layout="@layout/dock_info_bottom_area_overlay" />
-
- <include
- layout="@layout/keyguard_bottom_area"
- android:visibility="gone" />
-
- <ViewStub
- android:id="@+id/keyguard_user_switcher_stub"
- android:layout="@layout/keyguard_user_switcher"
- android:layout_height="match_parent"
- android:layout_width="match_parent" />
-
- <include layout="@layout/status_bar_expanded_plugin_frame"/>
-
- <com.android.keyguard.LockIconView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:id="@+id/lock_icon_view" />
+ <FrameLayout
+ android:id="@+id/preview_container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ </FrameLayout>
</com.android.systemui.statusbar.phone.NotificationPanelView>
diff --git a/packages/SystemUI/res/layout/super_notification_shade.xml b/packages/SystemUI/res/layout/super_notification_shade.xml
index bea50e8..08284a0 100644
--- a/packages/SystemUI/res/layout/super_notification_shade.xml
+++ b/packages/SystemUI/res/layout/super_notification_shade.xml
@@ -51,14 +51,6 @@
sysui:ignoreRightInset="true"
/>
- <com.android.systemui.scrim.ScrimView
- android:id="@+id/scrim_notifications"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:importantForAccessibility="no"
- sysui:ignoreRightInset="true"
- />
-
<com.android.systemui.statusbar.LightRevealScrim
android:id="@+id/light_reveal_scrim"
android:layout_width="match_parent"
diff --git a/packages/SystemUI/res/layout/wallet_fullscreen.xml b/packages/SystemUI/res/layout/wallet_fullscreen.xml
index d365aa3..aceefee 100644
--- a/packages/SystemUI/res/layout/wallet_fullscreen.xml
+++ b/packages/SystemUI/res/layout/wallet_fullscreen.xml
@@ -22,60 +22,67 @@
android:layout_height="match_parent"
android:clipChildren="false">
<Toolbar
- android:id="@+id/action_bar"
- style="?android:attr/actionBarStyle"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:background="@android:color/transparent"
- android:navigationContentDescription="@null" />
+ android:id="@+id/action_bar"
+ style="?android:attr/actionBarStyle"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="@android:color/transparent"
+ android:navigationContentDescription="@null" />
<LinearLayout
android:id="@+id/card_carousel_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="48dp"
android:orientation="vertical">
- <ImageView
- android:id="@+id/icon"
- android:layout_width="@dimen/wallet_screen_header_view_size"
- android:layout_height="@dimen/wallet_screen_header_view_size"
- android:layout_gravity="center_horizontal"
- android:layout_marginVertical="10dp"
- android:scaleType="center"
- android:contentDescription="@null"/>
- <TextView
- android:id="@+id/label"
+ <androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- style="@style/Wallet.TextAppearance"
- android:textAlignment="center"/>
+ android:layout_height="0dp"
+ android:layout_weight="1">
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:orientation="vertical">
+ <ImageView
+ android:id="@+id/icon"
+ android:layout_width="@dimen/wallet_screen_header_view_size"
+ android:layout_height="@dimen/wallet_screen_header_view_size"
+ android:layout_gravity="center_horizontal"
+ android:layout_marginVertical="10dp"
+ android:scaleType="center"
+ android:contentDescription="@null"/>
+ <TextView
+ android:id="@+id/label"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ style="@style/Wallet.TextAppearance"
+ android:textAlignment="center"/>
- <com.android.systemui.wallet.ui.WalletCardCarousel
- android:id="@+id/card_carousel"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:transitionName="dotIndicator"
- android:clipChildren="false"
- android:clipToPadding="false"
- android:layout_marginVertical="24dp"/>
-
- <Button
- android:id="@+id/wallet_action_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal"
- android:layout_marginVertical="16dp"
- android:paddingVertical="@dimen/wallet_button_vertical_padding"
- android:paddingHorizontal="@dimen/wallet_button_horizontal_padding"
- android:background="@drawable/wallet_action_button_bg"
- android:textColor="?androidprv:attr/textColorPrimaryInverse"
- android:textAlignment="center"
- android:visibility="gone"/>
-
+ <com.android.systemui.wallet.ui.WalletCardCarousel
+ android:id="@+id/card_carousel"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:transitionName="dotIndicator"
+ android:clipChildren="false"
+ android:clipToPadding="false"
+ android:layout_marginVertical="24dp"/>
+ <Button
+ android:id="@+id/wallet_action_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:layout_marginVertical="16dp"
+ android:paddingVertical="@dimen/wallet_button_vertical_padding"
+ android:paddingHorizontal="@dimen/wallet_button_horizontal_padding"
+ android:background="@drawable/wallet_action_button_bg"
+ android:textColor="?androidprv:attr/textColorPrimaryInverse"
+ android:textAlignment="center"
+ android:visibility="gone"/>
+ </LinearLayout>
+ </androidx.core.widget.NestedScrollView>
<View
android:layout_width="match_parent"
android:layout_height="0dp"
- android:layout_weight="1"/>
-
+ android:layout_weight="0.1"/>
<Button
android:id="@+id/wallet_app_button"
android:layout_width="wrap_content"
@@ -88,7 +95,6 @@
android:textColor="?androidprv:attr/colorAccentPrimary"
android:textAlignment="center"
android:layout_marginVertical="24dp"/>
-
</LinearLayout>
<include layout="@layout/wallet_empty_state"/>
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index e000ff4..3c936a0 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -136,6 +136,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Kamera"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Foon"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Stembystand"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"Beursie"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"Ontsluit"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Toestel is gesluit"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Wat tans vir vingerafdruk"</string>
@@ -291,7 +292,7 @@
<string name="accessibility_casting_turned_off" msgid="1387906158563374962">"Uitsaai van skerm gestaak."</string>
<string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Werkmodus is onderbreek."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Werkmodus is aan."</string>
- <string name="accessibility_quick_settings_work_mode_changed_off" msgid="2653550342355027441">"Werkmodus is verander na onderbreek."</string>
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Werkmodus is onderbreek."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Werkmodus is aangeskakel."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Databespaarder is afgeskakel."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Databespaarder is aangeskakel."</string>
@@ -1150,4 +1151,6 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"staaf"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"gaan by toestel in"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Gebruik vingerafdruk om oop te maak"</string>
+ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Stawing word vereis. Raak die vingerafdruksensor om te staaf."</string>
+ <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Oproep aan die gang"</string>
</resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index e69ab3f..c77dd57 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -136,6 +136,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"ካሜራ"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"ስልክ"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"የድምጽ እርዳታ"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"የኪስ ቦርሳ"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"ክፈት"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"መሣሪያ ተቆልፏል"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"የጣት አሻራን በመጠባበቅ ላይ"</string>
@@ -289,11 +290,9 @@
<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_casting_turned_off" msgid="1387906158563374962">"ማያ ገጽ መውሰድ ቆሟል።"</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"የሥራ ሁነታ ባለበት ቆሟል።"</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"የሥራ ሁነታ በርቷል።"</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"የሥራ ሁነታ ባለበት ቆሟል።"</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"የሥራ ሁነታ በርቷል።"</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"ውሂብ ቆጣቢ ጠፍቷል።"</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"ውሂብ ቆጣቢ በርቷል።"</string>
@@ -412,8 +411,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"<xliff:g id="DATA_LIMIT">%s</xliff:g> ገደብ"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"የ<xliff:g id="DATA_LIMIT">%s</xliff:g> ማስጠንቀቂያ"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"የሥራ መገለጫ"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"ባለበት ቆሟል"</string>
<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>
@@ -672,12 +670,10 @@
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"ሁሉንም አሳይ"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"ለመክፈል ይክፈቱ"</string>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"አልተዋቀረም"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ለማየት ይክፈቱ"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"የእርስዎን ካርዶች ማግኘት ላይ ችግር ነበር፣ እባክዎ ቆይተው እንደገና ይሞክሩ"</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"የገጽ መቆለፊያ ቅንብሮች"</string>
<string name="status_bar_work" msgid="5238641949837091056">"የስራ መገለጫ"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"የአውሮፕላን ሁነታ"</string>
<string name="add_tile" msgid="6239678623873086686">"ሰቅ ያክሉ"</string>
@@ -867,8 +863,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"በርቷል"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"ጠፍቷል"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"አይገኝም"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"ተሰናክሏል"</string>
<string name="nav_bar" msgid="4642708685386136807">"የአሰሳ አሞሌ"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"አቀማመጥ"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"ተጨማሪ የግራ አዝራር ዓይነት"</string>
@@ -1156,4 +1151,6 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"ያረጋግጡ"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"መሣሪያን ያስገቡ"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"ለመክፈት የጣት አሻራ ይጠቀሙ"</string>
+ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"ማረጋገጥ ያስፈልጋል። ለማረጋገጥ የጣት አሻራ ዳሳሹን ይንኩ።"</string>
+ <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"በመካሄድ ላይ የስልክ ጥሪ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index cfbab4b..a3a00ed 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"الكاميرا"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"الهاتف"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"المساعد الصوتي"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"فتح القفل"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"الجهاز مُقفل."</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"في انتظار بصمة الإصبع"</string>
@@ -289,11 +291,9 @@
<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_casting_turned_off" msgid="1387906158563374962">"توقف إرسال الشاشة."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"تم إيقاف وضع العمل مؤقتًا."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"وضع العمل قيد التشغيل."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"تم إيقاف وضع العمل مؤقتًا."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"تم تفعيل وضع العمل."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"تم إيقاف توفير البيانات."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"تم تفعيل توفير البيانات."</string>
@@ -420,8 +420,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"قيد <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"تحذير <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"الملف الشخصي للعمل"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"متوقف مؤقتًا"</string>
<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>
@@ -481,14 +480,10 @@
<string name="interruption_level_none_twoline" msgid="8579382742855486372">"كتم الصوت\nتمامًا"</string>
<string name="interruption_level_priority_twoline" msgid="8523482736582498083">"الأولوية \nفقط"</string>
<string name="interruption_level_alarms_twoline" msgid="2045067991335708767">"التنبيهات\nفقط"</string>
- <!-- no translation found for keyguard_indication_charging_time_wireless (577856646141738675) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time (6492711711891071502) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_fast (8390311020603859480) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_slowly (301936949731705417) -->
- <skip />
+ <string name="keyguard_indication_charging_time_wireless" msgid="577856646141738675">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • جارٍ الشحن لاسلكيًا • ستمتلئ البطارية خلال <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • جارٍ الشحن • ستمتلئ البطارية خلال <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • جارٍ الشحن سريعًا • ستمتلئ البطارية خلال <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • جارٍ الشحن ببطء • ستمتلئ البطارية خلال <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"تبديل المستخدم"</string>
<string name="accessibility_multi_user_switch_switcher_with_current" msgid="5759855008166759399">"تبديل المستخدم، المستخدم الحالي <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_inactive" msgid="383168614528618402">"المستخدم الحالي <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -534,7 +529,7 @@
<string name="manage_notifications_text" msgid="6885645344647733116">"إدارة"</string>
<string name="manage_notifications_history_text" msgid="57055985396576230">"السجلّ"</string>
<string name="notification_section_header_incoming" msgid="850925217908095197">"الإشعارات الجديدة"</string>
- <string name="notification_section_header_gentle" msgid="6804099527336337197">"صامت"</string>
+ <string name="notification_section_header_gentle" msgid="6804099527336337197">"صامتة"</string>
<string name="notification_section_header_alerting" msgid="5581175033680477651">"الإشعارات"</string>
<string name="notification_section_header_conversations" msgid="821834744538345661">"المحادثات"</string>
<string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"محو جميع الإشعارات الصامتة"</string>
@@ -688,12 +683,10 @@
<string name="wallet_title" msgid="5369767670735827105">"المحفظة"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"عرض الكل"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"فتح القفل للدفع"</string>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"لم يتم الإعداد."</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"فتح القفل للاستخدام"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"حدثت مشكلة أثناء الحصول على البطاقات، يُرجى إعادة المحاولة لاحقًا."</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"إعدادات شاشة القفل"</string>
<string name="status_bar_work" msgid="5238641949837091056">"الملف الشخصي للعمل"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"وضع الطيران"</string>
<string name="add_tile" msgid="6239678623873086686">"إضافة فئة"</string>
@@ -743,7 +736,7 @@
<string name="inline_block_button" msgid="479892866568378793">"حظر"</string>
<string name="inline_keep_button" msgid="299631874103662170">"الاستمرار في تلقّي الإشعارات"</string>
<string name="inline_minimize_button" msgid="1474436209299333445">"تصغير"</string>
- <string name="inline_silent_button_silent" msgid="525243786649275816">"صامت"</string>
+ <string name="inline_silent_button_silent" msgid="525243786649275816">"صامتة"</string>
<string name="inline_silent_button_stay_silent" msgid="2129254868305468743">"متابعة عرض الإشعارات بدون صوت"</string>
<string name="inline_silent_button_alert" msgid="5705343216858250354">"تنبيه"</string>
<string name="inline_silent_button_keep_alerting" msgid="6577845442184724992">"متابعة إرسال التنبيهات"</string>
@@ -891,8 +884,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"مفعّل"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"متوقف"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"غير متوفّر"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"غير مفعّل"</string>
<string name="nav_bar" msgid="4642708685386136807">"شريط التنقل"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"التنسيق"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"نوع زر اليسار الإضافي"</string>
@@ -1149,11 +1141,11 @@
<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="recent_conversations" msgid="8531874684782574622">"المحادثات الأخيرة"</string>
+ <string name="recent_conversations" msgid="8531874684782574622">"المحادثات الحديثة"</string>
<string name="okay" msgid="6490552955618608554">"حسنًا"</string>
<string name="timestamp" msgid="6577851592534538533">"قبل <xliff:g id="DURATION">%1$s</xliff:g>"</string>
<string name="less_than_timestamp" msgid="6598972791137724517">"قبل أقل من <xliff:g id="DURATION">%1$s</xliff:g>"</string>
- <string name="over_timestamp" msgid="4765793502859358634">"قبل أكثر <xliff:g id="DURATION">%1$s</xliff:g>"</string>
+ <string name="over_timestamp" msgid="4765793502859358634">"قبل أكثر من <xliff:g id="DURATION">%1$s</xliff:g>"</string>
<string name="birthday_status" msgid="2596961629465396761">"تاريخ الميلاد"</string>
<string name="birthday_status_content_description" msgid="682836371128282925">"إنه يوم ميلاد <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="upcoming_birthday_status" msgid="2005452239256870351">"تاريخ ميلاد قريب"</string>
@@ -1172,7 +1164,7 @@
<string name="status_before_loading" msgid="1500477307859631381">"سيظهر المحتوى قريبًا."</string>
<string name="missed_call" msgid="4228016077700161689">"مكالمة فائتة"</string>
<string name="messages_count_overflow_indicator" msgid="7850934067082006043">"+<xliff:g id="NUMBER">%d</xliff:g>"</string>
- <string name="people_tile_description" msgid="8154966188085545556">"عرض أحدث الرسائل والمكلمات الفائتة وآخر أخبار الحالة"</string>
+ <string name="people_tile_description" msgid="8154966188085545556">"عرض أحدث الرسائل والمكالمات الفائتة والتغييرات في الحالة"</string>
<string name="people_tile_title" msgid="6589377493334871272">"محادثة"</string>
<string name="new_notification_text_content_description" msgid="5574393603145263727">"تم إرسال رسالة من <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"تم إرسال صورة من <xliff:g id="NAME">%1$s</xliff:g>."</string>
@@ -1184,4 +1176,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"المصادقة"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"الدخول إلى الجهاز"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"يمكنك استخدام بصمة الإصبع للفتح"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ar/strings_tv.xml b/packages/SystemUI/res/values-ar/strings_tv.xml
index 7297c89..769999f 100644
--- a/packages/SystemUI/res/values-ar/strings_tv.xml
+++ b/packages/SystemUI/res/values-ar/strings_tv.xml
@@ -21,8 +21,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="mic_active" msgid="5766614241012047024">"الميكروفون نشط"</string>
<string name="app_accessed_mic" msgid="2754428675130470196">"تمكن %1$s من الوصول إلى الميكروفون الخاص بك."</string>
- <string name="notification_vpn_connected" msgid="3891023882833274730">"الشبكة الافتراضية الخاصة (VPN) متصلة."</string>
- <string name="notification_vpn_disconnected" msgid="7150747626448044843">"الشبكة الافتراضية الخاصة (VPN) غير متصلة."</string>
+ <string name="notification_vpn_connected" msgid="3891023882833274730">"شبكة VPN متصلة."</string>
+ <string name="notification_vpn_disconnected" msgid="7150747626448044843">"شبكة VPN غير متصلة."</string>
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"عبر <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"الإشعارات"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"ما من إشعارات"</string>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index d20b67d..0fba949 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"কেমেৰা"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"ফ\'ন"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"কণ্ঠধ্বনিৰে সহায়"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"আনলক কৰক"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"ডিভাইচটো লক হৈ আছে"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"ফিংগাৰপ্ৰিণ্টৰ বাবে ৰৈ থকা হৈছে"</string>
@@ -289,11 +291,9 @@
<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_casting_turned_off" msgid="1387906158563374962">"স্ক্ৰীণ কাষ্টিং বন্ধ কৰা হ’ল।"</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"কৰ্মস্থান ম’ড পজ হৈ আছে।"</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"কৰ্মস্থান ম\'ড অন হৈ আছে।"</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"কৰ্মস্থান ম’ড পজ হৈ আছে।"</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"কৰ্মস্থান ম\'ড অন কৰা হ’ল।"</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"ডেটা সঞ্চয়কাৰী সুবিধা অফ কৰা হ’ল।"</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"ডেটা সঞ্চয়কাৰী সুবিধা অন কৰা হ’ল।"</string>
@@ -412,8 +412,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"<xliff:g id="DATA_LIMIT">%s</xliff:g> সীমা"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"<xliff:g id="DATA_LIMIT">%s</xliff:g> সকীয়নি"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"কৰ্মস্থানৰ প্ৰ\'ফাইল"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"পজ হৈ আছে"</string>
<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>
@@ -473,14 +472,10 @@
<string name="interruption_level_none_twoline" msgid="8579382742855486372">"সম্পূর্ণ \n নিৰৱতা"</string>
<string name="interruption_level_priority_twoline" msgid="8523482736582498083">"কেৱল\nগুৰুত্বপূৰ্ণ"</string>
<string name="interruption_level_alarms_twoline" msgid="2045067991335708767">"কেৱল\nএলাৰ্মসমূহ"</string>
- <!-- no translation found for keyguard_indication_charging_time_wireless (577856646141738675) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time (6492711711891071502) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_fast (8390311020603859480) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_slowly (301936949731705417) -->
- <skip />
+ <string name="keyguard_indication_charging_time_wireless" msgid="577856646141738675">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • বেতাঁৰৰ দ্বাৰা চাৰ্জ হৈ আছে • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>ত সম্পূৰ্ণ হ’ব"</string>
+ <string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • চাৰ্জ হৈ আছে • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>ত সম্পূৰ্ণ হ’ব"</string>
+ <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • দ্ৰুতগতিৰে চাৰ্জ হৈ আছে • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>ত সম্পূৰ্ণ হ’ব"</string>
+ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • লাহে লাহে চাৰ্জ হৈ আছে • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>ত সম্পূৰ্ণ হ’ব"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ব্যৱহাৰকাৰী সলনি কৰক"</string>
<string name="accessibility_multi_user_switch_switcher_with_current" msgid="5759855008166759399">"ব্যৱহাৰকাৰী সলনি কৰক, বৰ্তমানৰ ব্যৱহাৰকাৰী <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_inactive" msgid="383168614528618402">"বর্তমানৰ ব্যৱহাৰকাৰী <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -676,12 +671,10 @@
<string name="wallet_title" msgid="5369767670735827105">"ৱালেট"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"আটাইবোৰ দেখুৱাওক"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"পৰিশোধ কৰিবলৈ আনলক কৰক"</string>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"ছেট আপ কৰা হোৱা নাই"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ব্যৱহাৰ কৰিবলৈ আনলক কৰক"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"আপোনাৰ কাৰ্ড লাভ কৰোঁতে এটা সমস্যা হৈছে, অনুগ্ৰহ কৰি পাছত পুনৰ চেষ্টা কৰক"</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"লক স্ক্ৰীনৰ ছেটিং"</string>
<string name="status_bar_work" msgid="5238641949837091056">"কৰ্মস্থানৰ প্ৰ\'ফাইল"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"এয়াৰপ্লেইন ম\'ড"</string>
<string name="add_tile" msgid="6239678623873086686">"টাইল যোগ দিয়ক"</string>
@@ -871,8 +864,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"অন"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"অফ"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"উপলব্ধ নহয়"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"অক্ষম কৰা আছে"</string>
<string name="nav_bar" msgid="4642708685386136807">"নেভিগেশ্বন দণ্ড"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"লেআউট"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"বাওঁ বুটামৰ অতিৰিক্ত প্ৰকাৰ"</string>
@@ -1160,4 +1152,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"বিশ্বাসযোগ্যতা প্ৰমাণ কৰক"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"ডিভাইচ আনলক কৰক"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"খুলিবলৈ ফিংগাৰপ্ৰিণ্ট ব্যৱহাৰ কৰক"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index d30d8ab..7babf41 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Kamera"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Telefon"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Səs Yardımçısı"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"Kiliddən çıxarın"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Cihaz kilidlənib"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Barmaq izi gözlənilir"</string>
@@ -289,11 +291,9 @@
<string name="accessibility_quick_settings_hotspot_changed_off" msgid="7002061268910095176">"Mobil hotspot deaktivdir."</string>
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2576895346762408840">"Mobil hotspot aktivdir."</string>
<string name="accessibility_casting_turned_off" msgid="1387906158563374962">"Ekran yayımı dayandırıldı."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"İş rejiminə pauza verilib."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"İş rejimi aktivdir."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"İş rejiminə pauza verilib."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"İş rejimi yanılıdır."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Trafikə qənaət edilmir."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Trafikə qənaət edilir."</string>
@@ -412,8 +412,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"<xliff:g id="DATA_LIMIT">%s</xliff:g> limit"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"<xliff:g id="DATA_LIMIT">%s</xliff:g> xəbərdarlığı"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"İş profili"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"Pauza verilib"</string>
<string name="quick_settings_night_display_label" msgid="8180030659141778180">"Gecə işığı"</string>
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Qürubda aktiv ediləcək"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"Şəfəq vaxtına qədər"</string>
@@ -473,14 +472,10 @@
<string name="interruption_level_none_twoline" msgid="8579382742855486372">"Tam\nsakitlik"</string>
<string name="interruption_level_priority_twoline" msgid="8523482736582498083">"Yalnız\nprioritet"</string>
<string name="interruption_level_alarms_twoline" msgid="2045067991335708767">"Yalnız\nalarmlar"</string>
- <!-- no translation found for keyguard_indication_charging_time_wireless (577856646141738675) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time (6492711711891071502) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_fast (8390311020603859480) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_slowly (301936949731705417) -->
- <skip />
+ <string name="keyguard_indication_charging_time_wireless" msgid="577856646141738675">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Simsiz şarj edilir • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> sonra dolacaq"</string>
+ <string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Şarj edilir • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> sonra dolacaq"</string>
+ <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Sürətlə şarj edilir • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> sonra dolacaq"</string>
+ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Asta şarj edilir • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> sonra dolacaq"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Switch user"</string>
<string name="accessibility_multi_user_switch_switcher_with_current" msgid="5759855008166759399">"İstifadəçiləri dəyişin, indiki istifadəçi: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_inactive" msgid="383168614528618402">"Cari istifadəçi <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -676,12 +671,10 @@
<string name="wallet_title" msgid="5369767670735827105">"Pulqabı"</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>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Quraşdırılmayıb"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"İstifadə etmək üçün kiliddən çıxarın"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Kartların əldə edilməsində problem oldu, sonra yenidən cəhd edin"</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Kilid ekranı ayarları"</string>
<string name="status_bar_work" msgid="5238641949837091056">"İş profili"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Təyyarə rejimi"</string>
<string name="add_tile" msgid="6239678623873086686">"Xana əlavə edin"</string>
@@ -871,8 +864,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"Aktiv"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"Deaktiv"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"Əlçatan deyil"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"Deaktiv edilib"</string>
<string name="nav_bar" msgid="4642708685386136807">"Naviqasiya paneli"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"Tərtibat"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"Əlavə sol düymə növü"</string>
@@ -1160,4 +1152,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"doğrulayın"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"cihaz daxil edin"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Açmaq üçün barmaq izindən istifadə edin"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 7c8d105..4451304 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Kamera"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Telefon"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Glasovna pomoć"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"Otključajte"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Uređaj je zaključan"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Čeka se otisak prsta"</string>
@@ -289,11 +291,9 @@
<string name="accessibility_quick_settings_hotspot_changed_off" msgid="7002061268910095176">"Mobilni hotspot je isključen."</string>
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2576895346762408840">"Mobilni hotspot je uključen."</string>
<string name="accessibility_casting_turned_off" msgid="1387906158563374962">"Prebacivanje ekrana je zaustavljeno."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Poslovni režim je pauziran."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Režim rada je uključen."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Poslovni režim je pauziran."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Režim rada je uključen."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Ušteda podataka je isključena."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Ušteda podataka je uključena."</string>
@@ -414,8 +414,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"Ograničenje od <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"Upozorenje za <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"Poslovni profil"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"Pauzirano"</string>
<string name="quick_settings_night_display_label" msgid="8180030659141778180">"Noćno svetlo"</string>
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Uključuje se po zalasku sunca"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"Do izlaska sunca"</string>
@@ -675,12 +674,10 @@
<string name="wallet_title" msgid="5369767670735827105">"Novčanik"</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>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Nije podešeno"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Otključaj radi korišćenja"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Došlo je do problema pri preuzimanju kartica. Probajte ponovo kasnije"</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Podešavanja zaključanog ekrana"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Poslovni profil"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Režim rada u avionu"</string>
<string name="add_tile" msgid="6239678623873086686">"Dodaj pločicu"</string>
@@ -872,8 +869,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"Uključeno"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"Isključeno"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"Nedostupno"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"Onemogućeno"</string>
<string name="nav_bar" msgid="4642708685386136807">"Traka za navigaciju"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"Raspored"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"Dodatni tip levog dugmeta"</string>
@@ -1146,7 +1142,7 @@
<string name="audio_status" msgid="4237055636967709208">"Sluša se"</string>
<string name="game_status" msgid="1340694320630973259">"Igra se"</string>
<string name="empty_user_name" msgid="3389155775773578300">"Prijatelji"</string>
- <string name="empty_status" msgid="5938893404951307749">"Ćaskamo večeras!"</string>
+ <string name="empty_status" msgid="5938893404951307749">"Ćaskamo večeras?"</string>
<string name="status_before_loading" msgid="1500477307859631381">"Sadržaj će se uskoro pojaviti"</string>
<string name="missed_call" msgid="4228016077700161689">"Propušten poziv"</string>
<string name="messages_count_overflow_indicator" msgid="7850934067082006043">"<xliff:g id="NUMBER">%d</xliff:g>+"</string>
@@ -1162,4 +1158,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"potvrdite identitet"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"unesite uređaj"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Otvorite pomoću otiska prsta"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index eed1535..26d4dff6e 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Камера"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Тэлефон"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Галасавая дапамога"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"Разблакiраваць"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Прылада заблакіравана"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Чаканне ўводу даных адбітка пальца"</string>
@@ -289,11 +291,9 @@
<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_casting_turned_off" msgid="1387906158563374962">"Трансляцыя экрана спынена."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Працоўны рэжым прыпынены."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Рэжым працы ўкл."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Працоўны рэжым прыпынены."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Рэжым працы ўключаны."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Эканомія трафіка адключана."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Эканомія трафіка ўключана."</string>
@@ -416,8 +416,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"Ліміт <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"Папярэджанне: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"Працоўны профіль"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"Прыпынена"</string>
<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>
@@ -477,14 +476,10 @@
<string name="interruption_level_none_twoline" msgid="8579382742855486372">"Поўная\nцішыня"</string>
<string name="interruption_level_priority_twoline" msgid="8523482736582498083">"Толькі\nпрыярытэтныя"</string>
<string name="interruption_level_alarms_twoline" msgid="2045067991335708767">"Толькі\nбудзільнікі"</string>
- <!-- no translation found for keyguard_indication_charging_time_wireless (577856646141738675) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time (6492711711891071502) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_fast (8390311020603859480) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_slowly (301936949731705417) -->
- <skip />
+ <string name="keyguard_indication_charging_time_wireless" msgid="577856646141738675">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ідзе бесправадная зарадка • Поўны зарад праз <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ідзе зарадка • Поўны зарад праз <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ідзе хуткая зарадка • Поўны зарад праз <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ідзе павольная зарадка • Поўны зарад праз <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Перайсці да іншага карыстальніка"</string>
<string name="accessibility_multi_user_switch_switcher_with_current" msgid="5759855008166759399">"Перайсці да іншага карыстальніка, бягучы карыстальнік <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_inactive" msgid="383168614528618402">"Бягучы карыстальнік <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -682,12 +677,10 @@
<string name="wallet_title" msgid="5369767670735827105">"Кашалёк"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Паказаць усе"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Разблакіраваць для аплаты"</string>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Не наладжана"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Разблакіраваць для выкарыстання"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Узнікла праблема з загрузкай вашых карт. Паўтарыце спробу пазней"</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Налады экрана блакіроўкі"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Працоўны профіль"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Рэжым палёту"</string>
<string name="add_tile" msgid="6239678623873086686">"Дадаць плітку"</string>
@@ -881,8 +874,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"Уключана"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"Выключана"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"Недаступна"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"Выключана"</string>
<string name="nav_bar" msgid="4642708685386136807">"Панэль навігацыі"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"Раскладка"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"Дадатковы тып кнопкі \"ўлева\""</string>
@@ -1172,4 +1164,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"правесці аўтэнтыфікацыю"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"вызначыць прыладу"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Каб адкрыць, скарыстайце адбітак пальца"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 17480bf..9f4c899 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Камера"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Телефон"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Гласова помощ"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"Отключване"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Устройството е заключено"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Изчаква се отпечатък"</string>
@@ -289,11 +291,9 @@
<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_casting_turned_off" msgid="1387906158563374962">"Предаването на съдържанието от екрана спря."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Работният режим е на пауза."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Работният режим е включен."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Работният режим е на пауза."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Работният режим е включен."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Функцията „Икономия на данни“ е изключена."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Функцията „Икономия на данни“ е включена."</string>
@@ -412,8 +412,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"Ограничение от <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"Предупреждение: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"Служебен потребителски профил"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"На пауза"</string>
<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>
@@ -473,14 +472,10 @@
<string name="interruption_level_none_twoline" msgid="8579382742855486372">"Пълна\nтишина"</string>
<string name="interruption_level_priority_twoline" msgid="8523482736582498083">"Само\nс приоритет"</string>
<string name="interruption_level_alarms_twoline" msgid="2045067991335708767">"Само\nбудилници"</string>
- <!-- no translation found for keyguard_indication_charging_time_wireless (577856646141738675) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time (6492711711891071502) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_fast (8390311020603859480) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_slowly (301936949731705417) -->
- <skip />
+ <string name="keyguard_indication_charging_time_wireless" msgid="577856646141738675">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Зарежда се безжично • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до пълно зареждане"</string>
+ <string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Зарежда се • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до пълно зареждане"</string>
+ <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Зарежда се бързо • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до пълно зареждане"</string>
+ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Зарежда се бавно • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до пълно зареждане"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Превключване между потребителите"</string>
<string name="accessibility_multi_user_switch_switcher_with_current" msgid="5759855008166759399">"Превключване на потребителя – текущият е <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_inactive" msgid="383168614528618402">"Текущ потребител – <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -676,12 +671,10 @@
<string name="wallet_title" msgid="5369767670735827105">"Портфейл"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Показване на всички"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Отключване с цел плащане"</string>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Не е настроено"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Отключване с цел използване"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"При извличането на картите ви възникна проблем. Моля, опитайте отново по-късно"</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Настройки за заключения екран"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Потребителски профил в Work"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Самолетен режим"</string>
<string name="add_tile" msgid="6239678623873086686">"Добавяне на плочка"</string>
@@ -871,8 +864,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"Вкл."</string>
<string name="switch_bar_off" msgid="5669805115416379556">"Изкл."</string>
<string name="tile_unavailable" msgid="3095879009136616920">"Не е налице"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"Деактивирано"</string>
<string name="nav_bar" msgid="4642708685386136807">"Лента за навигация"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"Оформление"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"Тип на допълнителния ляв бутон"</string>
@@ -1144,11 +1136,11 @@
<string name="audio_status" msgid="4237055636967709208">"Слуша се"</string>
<string name="game_status" msgid="1340694320630973259">"Играете"</string>
<string name="empty_user_name" msgid="3389155775773578300">"Приятели"</string>
- <string name="empty_status" msgid="5938893404951307749">"Да разговаряме!"</string>
+ <string name="empty_status" msgid="5938893404951307749">"Да поговорим!"</string>
<string name="status_before_loading" msgid="1500477307859631381">"Съдържанието ще се покаже скоро"</string>
<string name="missed_call" msgid="4228016077700161689">"Пропуснато обаждане"</string>
<string name="messages_count_overflow_indicator" msgid="7850934067082006043">"Над <xliff:g id="NUMBER">%d</xliff:g>"</string>
- <string name="people_tile_description" msgid="8154966188085545556">"Преглеждайте скорошните съобщения, пропуснатите обаждания и актуална информация за състоянието"</string>
+ <string name="people_tile_description" msgid="8154966188085545556">"Преглеждайте скорошни съобщения, пропуснати обаждания и информация за състоянието"</string>
<string name="people_tile_title" msgid="6589377493334871272">"Разговор"</string>
<string name="new_notification_text_content_description" msgid="5574393603145263727">"<xliff:g id="NAME">%1$s</xliff:g> изпрати съобщение"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> изпрати изображение"</string>
@@ -1160,4 +1152,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"удостоверяване"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"вход в устройството"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Използвайте отпечатък за отваряне"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 73efaed..66c03b2 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"ক্যামেরা"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"ফোন"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"ভয়েস সহায়তা"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"আনলক করুন"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"ডিভাইস লক করা আছে"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"আঙ্গুলের ছাপের জন্য অপেক্ষা করা হচ্ছে"</string>
@@ -289,10 +291,9 @@
<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_casting_turned_off" msgid="1387906158563374962">"স্ক্রিন কাস্ট করা থেমেছে।"</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"\'অফিস\' মোড পজ করা আছে।"</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"কাজের মোড চালু আছে"</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
+ <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (6422896967647049692) -->
<skip />
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"কাজের মোড চালু আছে"</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"ডেটা সেভার বন্ধ আছে।"</string>
@@ -412,8 +413,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"সীমা <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"<xliff:g id="DATA_LIMIT">%s</xliff:g> সতর্কতা"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"কাজের প্রোফাইল"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"পজ করা আছে"</string>
<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>
@@ -672,12 +672,10 @@
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"সবকটি দেখুন"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"পেমেন্ট করতে ডিভাইস আনলক করুন"</string>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"সেট আপ করা নেই"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ব্যবহার করতে আনলক করুন"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"আপনার কার্ড সংক্রান্ত তথ্য পেতে সমস্যা হয়েছে, পরে আবার চেষ্টা করুন"</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"লক স্ক্রিন সেটিংস"</string>
<string name="status_bar_work" msgid="5238641949837091056">"কাজের প্রোফাইল"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"বিমান মোড"</string>
<string name="add_tile" msgid="6239678623873086686">"টাইল যোগ করুন"</string>
@@ -867,8 +865,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"চালু আছে"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"বন্ধ আছে"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"উপলভ্য নয়"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"বন্ধ করা আছে"</string>
<string name="nav_bar" msgid="4642708685386136807">"নেভিগেশন বার"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"লেআউট"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"অতিরিক্ত বাঁদিকের বোতামের ধরণ"</string>
@@ -1123,9 +1120,9 @@
<string name="priority_conversations" msgid="3967482288896653039">"গুরুত্বপূর্ণ কথোপকথন"</string>
<string name="recent_conversations" msgid="8531874684782574622">"সাম্প্রতিক কথোপকথন"</string>
<string name="okay" msgid="6490552955618608554">"ঠিক আছে"</string>
- <string name="timestamp" msgid="6577851592534538533">"<xliff:g id="DURATION">%1$s</xliff:g> ঘণ্টা আগে"</string>
+ <string name="timestamp" msgid="6577851592534538533">"<xliff:g id="DURATION">%1$s</xliff:g> আগে"</string>
<string name="less_than_timestamp" msgid="6598972791137724517">"<xliff:g id="DURATION">%1$s</xliff:g> থেকে কিছু কম সময় আগে"</string>
- <string name="over_timestamp" msgid="4765793502859358634">"<xliff:g id="DURATION">%1$s</xliff:g> সপ্তাহেরও আগে"</string>
+ <string name="over_timestamp" msgid="4765793502859358634">"এই সময়েরও বেশি আগে: <xliff:g id="DURATION">%1$s</xliff:g>"</string>
<string name="birthday_status" msgid="2596961629465396761">"জন্মদিন"</string>
<string name="birthday_status_content_description" msgid="682836371128282925">"এটি হল <xliff:g id="NAME">%1$s</xliff:g>-এর জন্মদিন"</string>
<string name="upcoming_birthday_status" msgid="2005452239256870351">"জন্মদিন শীঘ্রই আসছে"</string>
@@ -1156,4 +1153,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"যাচাই করিয়ে নিন"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"ডিভাইস আনলক করুন"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"খুলতে ফিঙ্গারপ্রিন্ট ব্যবহার করুন"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 5c9ec89..e536e67 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Kamera"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Telefon"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Glasovna pomoć"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"Otključaj"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Uređaj je zaključan"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Čeka se otisak prsta"</string>
@@ -289,11 +291,9 @@
<string name="accessibility_quick_settings_hotspot_changed_off" msgid="7002061268910095176">"Mobilna pristupna tačka je isključena."</string>
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2576895346762408840">"Mobilna pristupna tačka je uključena."</string>
<string name="accessibility_casting_turned_off" msgid="1387906158563374962">"Prebacivanje ekrana je zaustavljeno."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Poslovni način rada je pauziran."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Poslovni režim uključen."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Poslovni način rada je pauziran."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Poslovni režim je uključen."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Ušteda podataka je isključena."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Ušteda podataka je uključena."</string>
@@ -414,8 +414,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"Ograničenje <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"Upozorenje <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"Radni profil"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"Pauzirano"</string>
<string name="quick_settings_night_display_label" msgid="8180030659141778180">"Noćno svjetlo"</string>
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Uključuje se u sumrak"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"Do svitanja"</string>
@@ -675,12 +674,10 @@
<string name="wallet_title" msgid="5369767670735827105">"Novčanik"</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>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Nije postavljeno"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Otključajte da koristite"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Došlo je do problema prilikom preuzimanja vaših kartica. Pokušajte ponovo kasnije"</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Postavke zaključavanja ekrana"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Profil za posao"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Način rada u avionu"</string>
<string name="add_tile" msgid="6239678623873086686">"Dodaj pločicu"</string>
@@ -872,8 +869,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"Uključeno"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"Isključeno"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"Nedostupno"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"Onemogućeno"</string>
<string name="nav_bar" msgid="4642708685386136807">"Navigaciona traka"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"Raspored"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"Vrsta dodatnog dugmeta lijevo"</string>
@@ -1162,4 +1158,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"autentificiranje"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"pristup uređaju"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Otvorite pomoću otiska prsta"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index fc3b2f5..ec2a0a0 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Càmera"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Telèfon"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Assistència per veu"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"Desbloqueja"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Dispositiu bloquejat"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"S\'està esperant l\'empremta digital"</string>
@@ -289,11 +291,9 @@
<string name="accessibility_quick_settings_hotspot_changed_off" msgid="7002061268910095176">"El punt d\'accés mòbil està desactivat."</string>
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2576895346762408840">"El punt d\'accés mòbil està activat."</string>
<string name="accessibility_casting_turned_off" msgid="1387906158563374962">"S\'ha aturat l\'emissió de la pantalla."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Mode de feina en pausa."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"El mode de feina està activat."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Mode de feina pausat."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"S\'ha activat el mode de feina."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"S\'ha desactivat l\'Economitzador de dades."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"S\'ha activat l\'Economitzador de dades."</string>
@@ -412,8 +412,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"Límit: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"Advertiment: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"Perfil de treball"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"En pausa"</string>
<string name="quick_settings_night_display_label" msgid="8180030659141778180">"Llum nocturna"</string>
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Al vespre"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"Fins a l\'alba"</string>
@@ -672,12 +671,10 @@
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</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>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"No s\'ha configurat"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Desbloqueja per utilitzar"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Hi ha hagut un problema en obtenir les teves targetes; torna-ho a provar més tard"</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Configuració de la pantalla de bloqueig"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Perfil de treball"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Mode d\'avió"</string>
<string name="add_tile" msgid="6239678623873086686">"Afegeix un mosaic"</string>
@@ -867,8 +864,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"Activat"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"Desactivat"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"No disponible"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"Desactivat"</string>
<string name="nav_bar" msgid="4642708685386136807">"Barra de navegació"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"Disposició"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"Tipus de botó addicional de l\'esquerra"</string>
@@ -1156,4 +1152,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"autenticar"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"accedir al dispositiu"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Utilitza l\'empremta digital per obrir"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 4560cad..db334f2 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Fotoaparát"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Telefon"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Hlasová asistence"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"Odemknout"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Zařízení uzamčeno"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Čeká se na použití otisku"</string>
@@ -289,11 +291,9 @@
<string name="accessibility_quick_settings_hotspot_changed_off" msgid="7002061268910095176">"Mobile hotspot je vypnutý."</string>
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2576895346762408840">"Mobile hotspot je zapnutý."</string>
<string name="accessibility_casting_turned_off" msgid="1387906158563374962">"Odesílání obrazovky zastaveno."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Pracovní režim byl pozastaven."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Pracovní režim zapnutý"</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Pracovní režim byl pozastaven."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Pracovní režim je zapnutý."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Spořič dat byl vypnut."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Spořič dat byl zapnut."</string>
@@ -416,8 +416,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"Limit: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"Upozornění při <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"Pracovní profil"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"Pozastaveno"</string>
<string name="quick_settings_night_display_label" msgid="8180030659141778180">"Noční režim"</string>
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Při soumraku"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"Do svítání"</string>
@@ -678,12 +677,10 @@
<string name="wallet_title" msgid="5369767670735827105">"Peněženka"</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>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Není nastaveno"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Odemknout a použít"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Při načítání karet došlo k problému, zkuste to později"</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Nastavení obrazovky uzamčení"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Pracovní profil"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Režim Letadlo"</string>
<string name="add_tile" msgid="6239678623873086686">"Přidat dlaždici"</string>
@@ -877,8 +874,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"Zapnuto"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"Vypnuto"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"Nedostupné"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"Vypnuto"</string>
<string name="nav_bar" msgid="4642708685386136807">"Navigační panel"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"Rozvržení"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"Zvláštní typ tlačítka vlevo"</string>
@@ -1168,4 +1164,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"ověříte"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"zadáte zařízení"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"K otevření použijte otisk prstu"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index a30e0636..de4deff 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Kamera"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Telefon"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Taleassistent"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"Lås op"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Enheden er låst"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Venter på fingeraftryk"</string>
@@ -291,7 +293,7 @@
<string name="accessibility_casting_turned_off" msgid="1387906158563374962">"Casting af din skærm er stoppet."</string>
<string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Arbejdstilstand er på pause."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Arbejdstilstand er slået til."</string>
- <string name="accessibility_quick_settings_work_mode_changed_off" msgid="2653550342355027441">"Arbejdstilstand er sat på pause."</string>
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Arbejdstilstand er sat på pause."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Arbejdstilstand er slået til."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Datasparefunktionen er slået fra."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Datasparefunktionen er aktiveret."</string>
@@ -1150,4 +1152,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"godkende"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"få adgang til enheden"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Brug fingeraftryk for at åbne"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 19691c0..e6334e0 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Kamera"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Telefonnummer"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Sprachassistent"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"Entsperren"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Gerät gesperrt"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Auf Fingerabdruck wird gewartet"</string>
@@ -289,11 +291,9 @@
<string name="accessibility_quick_settings_hotspot_changed_off" msgid="7002061268910095176">"Der mobile Hotspot ist deaktiviert."</string>
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2576895346762408840">"Der mobile Hotspot ist aktiviert."</string>
<string name="accessibility_casting_turned_off" msgid="1387906158563374962">"Die Bildschirmübertragung wurde angehalten."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Arbeitsmodus pausiert."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Arbeitsmodus an."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Arbeitsmodus pausiert."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Arbeitsmodus aktiviert."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Der Datensparmodus ist deaktiviert."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Der Datensparmodus ist aktiviert."</string>
@@ -412,8 +412,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"<xliff:g id="DATA_LIMIT">%s</xliff:g> Datenlimit"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"Warnung für <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"Arbeitsprofil"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"Pausiert"</string>
<string name="quick_settings_night_display_label" msgid="8180030659141778180">"Nachtlicht"</string>
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"An bei Sonnenuntergang"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"Bis Sonnenaufgang"</string>
@@ -473,14 +472,10 @@
<string name="interruption_level_none_twoline" msgid="8579382742855486372">"Laut-\nlos"</string>
<string name="interruption_level_priority_twoline" msgid="8523482736582498083">"Nur\nwichtige"</string>
<string name="interruption_level_alarms_twoline" msgid="2045067991335708767">"Nur\nWecker"</string>
- <!-- no translation found for keyguard_indication_charging_time_wireless (577856646141738675) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time (6492711711891071502) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_fast (8390311020603859480) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_slowly (301936949731705417) -->
- <skip />
+ <string name="keyguard_indication_charging_time_wireless" msgid="577856646141738675">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Wird kabellos geladen • Voll in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Wird geladen • Voll in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Wird schnell geladen • Voll in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Wird langsam geladen • Voll in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Nutzer wechseln"</string>
<string name="accessibility_multi_user_switch_switcher_with_current" msgid="5759855008166759399">"Nutzer wechseln. Aktueller Nutzer: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_inactive" msgid="383168614528618402">"Aktueller Nutzer <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -676,12 +671,10 @@
<string name="wallet_title" msgid="5369767670735827105">"Geldbörse"</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>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Nicht eingerichtet"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Zum Verwenden entsperren"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Beim Abrufen deiner Karten ist ein Fehler aufgetreten – bitte versuch es später noch einmal"</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Einstellungen für den Sperrbildschirm"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Arbeitsprofil"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Flugmodus"</string>
<string name="add_tile" msgid="6239678623873086686">"Kachel hinzufügen"</string>
@@ -871,8 +864,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"An"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"Aus"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"Nicht verfügbar"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"Deaktiviert"</string>
<string name="nav_bar" msgid="4642708685386136807">"Navigationsleiste"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"Layout"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"Zusätzlicher linker Schaltflächentyp"</string>
@@ -1144,7 +1136,7 @@
<string name="audio_status" msgid="4237055636967709208">"Hört etwas"</string>
<string name="game_status" msgid="1340694320630973259">"Spielt"</string>
<string name="empty_user_name" msgid="3389155775773578300">"Freunde"</string>
- <string name="empty_status" msgid="5938893404951307749">"Chat heute Abend!"</string>
+ <string name="empty_status" msgid="5938893404951307749">"Heute Abend chatten!"</string>
<string name="status_before_loading" msgid="1500477307859631381">"Der Inhalt wird bald angezeigt"</string>
<string name="missed_call" msgid="4228016077700161689">"Verpasster Anruf"</string>
<string name="messages_count_overflow_indicator" msgid="7850934067082006043">"<xliff:g id="NUMBER">%d</xliff:g>+"</string>
@@ -1160,4 +1152,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"Authentifizieren"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"Eingeben des Geräts"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Mit Fingerabdruck öffnen"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index fd8af9d..8bc1765 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Φωτογραφική μηχανή"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Τηλέφωνο"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Φωνητική υποβοήθηση"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"Ξεκλείδωμα"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Η συσκευή κλειδώθηκε"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Αναμονή για δακτυλικό αποτύπωμα"</string>
@@ -289,11 +291,9 @@
<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_casting_turned_off" msgid="1387906158563374962">"Η μετάδοση της οθόνης διακόπηκε."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Η λειτουργία εργασίας τέθηκε σε παύση."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Η λειτουργία εργασίας είναι ενεργή."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Η λειτουργία εργασίας τέθηκε σε παύση."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Η λειτουργία εργασίας ενεργοποιήθηκε."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Η Εξοικονόμηση δεδομένων είναι ανενεργή."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Η Εξοικονόμηση δεδομένων είναι ενεργή."</string>
@@ -412,8 +412,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"Όριο <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"Προειδοποίηση για <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"Προφίλ εργασίας"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"Σε παύση"</string>
<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>
@@ -672,12 +671,10 @@
<string name="wallet_title" msgid="5369767670735827105">"Πορτοφόλι"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Εμφάνιση όλων"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Ξεκλείδωμα για πληρωμή"</string>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Δεν έχει ρυθμιστεί"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Ξεκλείδωμα για χρήση"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Παρουσιάστηκε πρόβλημα με τη λήψη των καρτών σας. Δοκιμάστε ξανά αργότερα"</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Ρυθμίσεις κλειδώματος οθόνης"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Προφίλ εργασίας"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Λειτουργία πτήσης"</string>
<string name="add_tile" msgid="6239678623873086686">"Προσθήκη πλακιδίου"</string>
@@ -867,8 +864,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"Ενεργό"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"Απενεργοποίηση"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"Μη διαθέσιμο"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"Ανενεργό"</string>
<string name="nav_bar" msgid="4642708685386136807">"Γραμμή πλοήγησης"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"Διάταξη"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"Επιπλέον τύπος αριστερού κουμπιού"</string>
@@ -1156,4 +1152,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"έλεγχος ταυτότητας"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"εισαγωγή συσκευής"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Χρήση δακτυλικού αποτυπώματος για άνοιγμα"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 25a34ae..428a565 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -136,6 +136,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Camera"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Phone"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Voice Assist"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"Unlock"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Device locked"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Waiting for fingerprint"</string>
@@ -291,7 +292,7 @@
<string name="accessibility_casting_turned_off" msgid="1387906158563374962">"Screen casting stopped."</string>
<string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Work mode paused."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Work mode on."</string>
- <string name="accessibility_quick_settings_work_mode_changed_off" msgid="2653550342355027441">"Work mode turned paused."</string>
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Work mode paused."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Work mode turned on."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Data Saver turned off."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Data Saver turned on."</string>
@@ -1150,4 +1151,6 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"Authenticate"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"enter device"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Use fingerprint to open"</string>
+ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Authentication required. Touch the fingerprint sensor to authenticate."</string>
+ <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Ongoing phone call"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index 3511d97..99ec519 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -136,6 +136,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Camera"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Phone"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Voice Assist"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"Unlock"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Device locked"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Waiting for fingerprint"</string>
@@ -291,7 +292,7 @@
<string name="accessibility_casting_turned_off" msgid="1387906158563374962">"Screen casting stopped."</string>
<string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Work mode paused."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Work mode on."</string>
- <string name="accessibility_quick_settings_work_mode_changed_off" msgid="2653550342355027441">"Work mode turned paused."</string>
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Work mode paused."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Work mode turned on."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Data Saver turned off."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Data Saver turned on."</string>
@@ -1150,4 +1151,6 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"Authenticate"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"enter device"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Use fingerprint to open"</string>
+ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Authentication required. Touch the fingerprint sensor to authenticate."</string>
+ <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Ongoing phone call"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 25a34ae..428a565 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -136,6 +136,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Camera"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Phone"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Voice Assist"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"Unlock"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Device locked"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Waiting for fingerprint"</string>
@@ -291,7 +292,7 @@
<string name="accessibility_casting_turned_off" msgid="1387906158563374962">"Screen casting stopped."</string>
<string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Work mode paused."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Work mode on."</string>
- <string name="accessibility_quick_settings_work_mode_changed_off" msgid="2653550342355027441">"Work mode turned paused."</string>
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Work mode paused."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Work mode turned on."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Data Saver turned off."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Data Saver turned on."</string>
@@ -1150,4 +1151,6 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"Authenticate"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"enter device"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Use fingerprint to open"</string>
+ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Authentication required. Touch the fingerprint sensor to authenticate."</string>
+ <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Ongoing phone call"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 25a34ae..428a565 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -136,6 +136,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Camera"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Phone"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Voice Assist"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"Unlock"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Device locked"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Waiting for fingerprint"</string>
@@ -291,7 +292,7 @@
<string name="accessibility_casting_turned_off" msgid="1387906158563374962">"Screen casting stopped."</string>
<string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Work mode paused."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Work mode on."</string>
- <string name="accessibility_quick_settings_work_mode_changed_off" msgid="2653550342355027441">"Work mode turned paused."</string>
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Work mode paused."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Work mode turned on."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Data Saver turned off."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Data Saver turned on."</string>
@@ -1150,4 +1151,6 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"Authenticate"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"enter device"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Use fingerprint to open"</string>
+ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Authentication required. Touch the fingerprint sensor to authenticate."</string>
+ <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Ongoing phone call"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index 04d0ade..11e32a759 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -136,6 +136,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Camera"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Phone"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Voice Assist"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"Unlock"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Device locked"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Waiting for fingerprint"</string>
@@ -291,7 +292,7 @@
<string name="accessibility_casting_turned_off" msgid="1387906158563374962">"Screen casting stopped."</string>
<string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Work mode paused."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Work mode on."</string>
- <string name="accessibility_quick_settings_work_mode_changed_off" msgid="2653550342355027441">"Work mode turned paused."</string>
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Work mode paused."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Work mode turned on."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Data Saver turned off."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Data Saver turned on."</string>
@@ -1150,4 +1151,6 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"authenticate"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"enter device"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Use fingerprint to open"</string>
+ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Authentication required. Touch the fingerprint sensor to authenticate."</string>
+ <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Ongoing phone call"</string>
</resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 58a31df..1b0e816 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -136,6 +136,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Cámara"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Teléfono"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Asistente voz"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"Desbloquear"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Dispositivo bloqueado"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Esperando huella dactilar"</string>
@@ -291,7 +292,7 @@
<string name="accessibility_casting_turned_off" msgid="1387906158563374962">"Transmisión de pantalla detenida"</string>
<string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Modo de trabajo pausado."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Modo de trabajo activado"</string>
- <string name="accessibility_quick_settings_work_mode_changed_off" msgid="2653550342355027441">"Se pausó el modo de trabajo."</string>
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Se pausó el modo de trabajo."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Se activó el modo de trabajo."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Se desactivó el Ahorro de datos."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Se activó el Ahorro de datos."</string>
@@ -1150,4 +1151,6 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"autenticar"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"ingresar al dispositivo"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Usa la huella dactilar para abrir"</string>
+ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Se requiere de una autenticación. Toca el sensor de huellas dactilares para autenticarte."</string>
+ <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Llamada en curso"</string>
</resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index a863111..33a8660 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Cámara"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Teléfono"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Asistente voz"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"Desbloquear"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Dispositivo bloqueado"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Esperando huella digital"</string>
@@ -289,11 +291,9 @@
<string name="accessibility_quick_settings_hotspot_changed_off" msgid="7002061268910095176">"Punto de acceso móvil desactivado."</string>
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2576895346762408840">"Punto de acceso móvil activado."</string>
<string name="accessibility_casting_turned_off" msgid="1387906158563374962">"Envío de pantalla detenido."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Modo de trabajo pausado."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Modo de trabajo activado."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Modo de trabajo pausado."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Modo de trabajo activado."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Ahorro de datos desactivado."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Ahorro de datos activado."</string>
@@ -412,8 +412,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"Límite de <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"Advertencia de <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"Perfil de trabajo"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"Pausado"</string>
<string name="quick_settings_night_display_label" msgid="8180030659141778180">"Luz nocturna"</string>
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Al atardecer"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"Hasta el amanecer"</string>
@@ -672,12 +671,10 @@
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</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>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Sin configurar"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Desbloquear para usar"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Se ha producido un problema al obtener tus tarjetas. Inténtalo de nuevo más tarde."</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Ajustes de pantalla de bloqueo"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Perfil de trabajo"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Modo avión"</string>
<string name="add_tile" msgid="6239678623873086686">"Añadir icono"</string>
@@ -867,8 +864,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"Activado"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"Desactivado"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"No disponible"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"Inhabilitado"</string>
<string name="nav_bar" msgid="4642708685386136807">"Barra de navegación"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"Diseño"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"Tipo de botón a la izquierda extra"</string>
@@ -1007,7 +1003,7 @@
<string name="auto_saver_enabled_text" msgid="7889491183116752719">"El modo Ahorro de batería se activará automáticamente cuando quede menos de un <xliff:g id="PERCENTAGE">%d</xliff:g> %% de batería."</string>
<string name="open_saver_setting_action" msgid="2111461909782935190">"Ajustes"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Entendido"</string>
- <string name="heap_dump_tile_name" msgid="2464189856478823046">"Volcar pila de SysUI"</string>
+ <string name="heap_dump_tile_name" msgid="2464189856478823046">"Volcar montículo de SysUI"</string>
<string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> está usando tu <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
<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>
@@ -1126,7 +1122,7 @@
<string name="timestamp" msgid="6577851592534538533">"Hace <xliff:g id="DURATION">%1$s</xliff:g>"</string>
<string name="less_than_timestamp" msgid="6598972791137724517">"Hace menos de <xliff:g id="DURATION">%1$s</xliff:g>"</string>
<string name="over_timestamp" msgid="4765793502859358634">"Hace más de <xliff:g id="DURATION">%1$s</xliff:g>"</string>
- <string name="birthday_status" msgid="2596961629465396761">"Fecha de nacimiento"</string>
+ <string name="birthday_status" msgid="2596961629465396761">"Cumpleaños"</string>
<string name="birthday_status_content_description" msgid="682836371128282925">"Es el cumpleaños de <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="upcoming_birthday_status" msgid="2005452239256870351">"Cumpleaños en breve"</string>
<string name="upcoming_birthday_status_content_description" msgid="2165036816803797148">"Se acerca el cumpleaños de <xliff:g id="NAME">%1$s</xliff:g>"</string>
@@ -1140,7 +1136,7 @@
<string name="audio_status" msgid="4237055636967709208">"Escuchando"</string>
<string name="game_status" msgid="1340694320630973259">"Reproduciendo"</string>
<string name="empty_user_name" msgid="3389155775773578300">"Amigos"</string>
- <string name="empty_status" msgid="5938893404951307749">"Charlemos esta noche"</string>
+ <string name="empty_status" msgid="5938893404951307749">"¿Hablamos luego?"</string>
<string name="status_before_loading" msgid="1500477307859631381">"El contenido se mostrará en breve"</string>
<string name="missed_call" msgid="4228016077700161689">"Llamada perdida"</string>
<string name="messages_count_overflow_indicator" msgid="7850934067082006043">"<xliff:g id="NUMBER">%d</xliff:g>+"</string>
@@ -1156,4 +1152,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"autenticarte"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"acceder al dispositivo"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Usa la huella digital para abrir"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index ff833d9..3d3a09b 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Kaamera"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Telefon"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Häälabi"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"Luku avamine"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Seade on lukustatud"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Sõrmejälje ootel"</string>
@@ -289,11 +291,9 @@
<string name="accessibility_quick_settings_hotspot_changed_off" msgid="7002061268910095176">"Mobiilside kuumkoht on välja lülitatud."</string>
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2576895346762408840">"Mobiilside kuumkoht on sisse lülitatud."</string>
<string name="accessibility_casting_turned_off" msgid="1387906158563374962">"Ekraanikuva ülekandmine on peatatud."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Töörežiim peatati."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Töörežiim on sees."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Töörežiim peatati."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Töörežiim on sisse lülitatud."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Andmemahu säästja on välja lülitatud."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Andmemahu säästja on sisse lülitatud."</string>
@@ -412,8 +412,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"Limiit: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"<xliff:g id="DATA_LIMIT">%s</xliff:g> hoiatus"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"Tööprofiil"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"Peatatud"</string>
<string name="quick_settings_night_display_label" msgid="8180030659141778180">"Öövalgus"</string>
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Sissel. päikeselooj."</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"Kuni päikesetõusuni"</string>
@@ -473,14 +472,10 @@
<string name="interruption_level_none_twoline" msgid="8579382742855486372">"Täielik\nvaikus"</string>
<string name="interruption_level_priority_twoline" msgid="8523482736582498083">"Ainult\nprioriteetsed"</string>
<string name="interruption_level_alarms_twoline" msgid="2045067991335708767">"Ainult\nalarmid"</string>
- <!-- no translation found for keyguard_indication_charging_time_wireless (577856646141738675) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time (6492711711891071502) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_fast (8390311020603859480) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_slowly (301936949731705417) -->
- <skip />
+ <string name="keyguard_indication_charging_time_wireless" msgid="577856646141738675">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Juhtmeta laadimine • Täis <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> pärast"</string>
+ <string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laadimine • Täis <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> pärast"</string>
+ <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Kiirlaadimine • Täis <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> pärast"</string>
+ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Aeglane laadimine • Täis <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> pärast"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Kasutaja vahetamine"</string>
<string name="accessibility_multi_user_switch_switcher_with_current" msgid="5759855008166759399">"Kasutaja vahetamine, praegune kasutaja: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_inactive" msgid="383168614528618402">"Praegune kasutaja <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -676,12 +671,10 @@
<string name="wallet_title" msgid="5369767670735827105">"Rahakott"</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>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Pole seadistatud"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Avage kasutamiseks"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Teie kaartide hankimisel ilmnes probleem, proovige hiljem uuesti"</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Lukustuskuva seaded"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Tööprofiil"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Lennukirežiim"</string>
<string name="add_tile" msgid="6239678623873086686">"Paani lisamine"</string>
@@ -871,8 +864,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"Sees"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"Väljas"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"Pole saadaval"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"Keelatud"</string>
<string name="nav_bar" msgid="4642708685386136807">"Navigeerimisriba"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"Paigutus"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"Täiendava vasaku nupu tüüp"</string>
@@ -1129,7 +1121,7 @@
<string name="okay" msgid="6490552955618608554">"OK"</string>
<string name="timestamp" msgid="6577851592534538533">"<xliff:g id="DURATION">%1$s</xliff:g> tagasi"</string>
<string name="less_than_timestamp" msgid="6598972791137724517">"Vähem kui <xliff:g id="DURATION">%1$s</xliff:g> tagasi"</string>
- <string name="over_timestamp" msgid="4765793502859358634">"Üle <xliff:g id="DURATION">%1$s</xliff:g> tagasi"</string>
+ <string name="over_timestamp" msgid="4765793502859358634">"Rohkem kui <xliff:g id="DURATION">%1$s</xliff:g> tagasi"</string>
<string name="birthday_status" msgid="2596961629465396761">"Sünnipäev"</string>
<string name="birthday_status_content_description" msgid="682836371128282925">"On kasutaja <xliff:g id="NAME">%1$s</xliff:g> sünnipäev"</string>
<string name="upcoming_birthday_status" msgid="2005452239256870351">"Peagi on sünnipäev"</string>
@@ -1160,4 +1152,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"autentimiseks"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"seadmesse sisenemiseks"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Kasutage avamiseks sõrmejälge"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 932ce3e..eb2bde3 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Kamera"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Telefonoa"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Ahots-laguntza"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"Desblokeatu"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Gailua blokeatuta dago"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Hatz-markaren zain"</string>
@@ -289,11 +291,9 @@
<string name="accessibility_quick_settings_hotspot_changed_off" msgid="7002061268910095176">"Wifi-gune mugikorra desaktibatu egin da."</string>
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2576895346762408840">"Wifi-gune mugikorra aktibatu egin da."</string>
<string name="accessibility_casting_turned_off" msgid="1387906158563374962">"Pantaila igortzeari utzi zaio."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Lan modua pausatuta dago."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Aktibatuta dago lan modua."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Pausatu egin da lan modua."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Aktibatuta dago lan modua."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Desaktibatuta dago datu-aurrezlea."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Aktibatuta dago datu-aurrezlea."</string>
@@ -412,8 +412,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"Muga: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"Abisua: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"Laneko profila"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"Pausatuta"</string>
<string name="quick_settings_night_display_label" msgid="8180030659141778180">"Gaueko argia"</string>
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Ilunabarrean"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"Ilunabarrera arte"</string>
@@ -672,12 +671,10 @@
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Erakutsi guztiak"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Desblokeatu ordaintzeko"</string>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Konfiguratu gabe"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Desblokeatu erabiltzeko"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Arazo bat izan da txartelak eskuratzean. Saiatu berriro geroago."</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Pantaila blokeatuaren ezarpenak"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Work profila"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Hegaldi modua"</string>
<string name="add_tile" msgid="6239678623873086686">"Gehitu lauza"</string>
@@ -867,8 +864,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"Aktibatuta"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"Desaktibatuta"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"Ez dago erabilgarri"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"Desgaituta"</string>
<string name="nav_bar" msgid="4642708685386136807">"Nabigazio-barra"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"Diseinua"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"Ezkerreko botoi gehigarriaren mota"</string>
@@ -1156,4 +1152,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"autentifikatu"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"sartu gailuan"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Erabili hatz-marka irekitzeko"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 89b4fbd..aacf905 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -136,6 +136,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"دوربین"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"تلفن"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"دستیار صوتی"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"باز کردن قفل"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"دستگاه قفل است"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"در انتظار اثر انگشت"</string>
@@ -291,7 +292,7 @@
<string name="accessibility_casting_turned_off" msgid="1387906158563374962">"فرستادن صفحه نمایش متوقف شد."</string>
<string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"حالت کار موقتاً متوقف شده است."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"حالت کار روشن."</string>
- <string name="accessibility_quick_settings_work_mode_changed_off" msgid="2653550342355027441">"حالت کار موقتاً متوقف شد."</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>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"صرفهجویی داده خاموش شد."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"صرفهجویی داده روشن شد."</string>
@@ -1150,4 +1151,6 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"اصالتسنجی کردن"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"وارد شدن به دستگاه"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"از اثر انگشت برای باز کردن قفل استفاده کنید"</string>
+ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"اصالتسنجی لازم است. برای اصالتسنجی، حسگر اثر انگشت را لمس کنید."</string>
+ <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"تماس تلفنی درحال انجام"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 6fc7855..674a4be 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Kamera"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Puhelin"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Ääniapuri"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"Avaa lukitus"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Laite lukittu"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Odotetaan sormenjälkeä"</string>
@@ -289,11 +291,9 @@
<string name="accessibility_quick_settings_hotspot_changed_off" msgid="7002061268910095176">"Mobiiliyhteyden hotspot poistettiin käytöstä."</string>
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2576895346762408840">"Mobiiliyhteyden hotspot otettiin käyttöön."</string>
<string name="accessibility_casting_turned_off" msgid="1387906158563374962">"Ruudun lähetys pysäytettiin."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Työtila keskeytetty."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Työtila on käytössä."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Työtila keskeytetty."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Työtila otettiin käyttöön."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Data Saver poistettiin käytöstä."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Data Saver otettiin käyttöön."</string>
@@ -412,8 +412,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"kiintiö <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"<xliff:g id="DATA_LIMIT">%s</xliff:g> – varoitus"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"Työprofiili"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"Keskeytetty"</string>
<string name="quick_settings_night_display_label" msgid="8180030659141778180">"Yövalo"</string>
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Auringon laskiessa"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"Auringonnousuun"</string>
@@ -473,14 +472,10 @@
<string name="interruption_level_none_twoline" msgid="8579382742855486372">"Täydellinen\nhiljaisuus"</string>
<string name="interruption_level_priority_twoline" msgid="8523482736582498083">"Vain\ntärkeät"</string>
<string name="interruption_level_alarms_twoline" msgid="2045067991335708767">"Vain\nherätykset"</string>
- <!-- no translation found for keyguard_indication_charging_time_wireless (577856646141738675) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time (6492711711891071502) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_fast (8390311020603859480) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_slowly (301936949731705417) -->
- <skip />
+ <string name="keyguard_indication_charging_time_wireless" msgid="577856646141738675">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Latautuu langattomasti • Täynnä <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> päästä"</string>
+ <string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Latautuu • Täynnä <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> päästä"</string>
+ <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Latautuu nopeasti • Täynnä <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> päästä"</string>
+ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Latautuu hitaasti • Täynnä <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> päästä"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Vaihda käyttäjää"</string>
<string name="accessibility_multi_user_switch_switcher_with_current" msgid="5759855008166759399">"Vaihda käyttäjä (nyt <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>)"</string>
<string name="accessibility_multi_user_switch_inactive" msgid="383168614528618402">"Nykyinen käyttäjä: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -676,12 +671,10 @@
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</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>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Ei otettu käyttöön"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Avaa lukitus ja käytä"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Korttien noutamisessa oli ongelma, yritä myöhemmin uudelleen"</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Lukitusnäytön asetukset"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Työprofiili"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Lentokonetila"</string>
<string name="add_tile" msgid="6239678623873086686">"Lisää ruutu"</string>
@@ -871,8 +864,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"Päällä"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"Pois päältä"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"Ei käytettävissä"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"Ei käytössä"</string>
<string name="nav_bar" msgid="4642708685386136807">"Navigointipalkki"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"Asettelu"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"Ylimääräinen vasen painiketyyppi"</string>
@@ -1160,4 +1152,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"todentaaksesi"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"avataksesi laitteen"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Avaa sormenjäljellä"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 7218b86..7bc9db9 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Appareil photo"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Téléphone"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Assistance vocale"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"Déverrouiller"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Appareil verrouillé"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"En attente de l\'empreinte digitale"</string>
@@ -289,11 +291,9 @@
<string name="accessibility_quick_settings_hotspot_changed_off" msgid="7002061268910095176">"Point d\'accès mobile désactivé."</string>
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2576895346762408840">"Point d\'accès mobile activé."</string>
<string name="accessibility_casting_turned_off" msgid="1387906158563374962">"Diffusion d\'écran arrêtée."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Mode professionnel interrompu."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Mode Travail activé."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Mode professionnel interrompu."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Le mode Travail est activé."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Mode Économiseur de données désactivé."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Mode Économiseur de données activé."</string>
@@ -412,8 +412,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"Limite : <xliff:g id="DATA_LIMIT">%s</xliff:g>"</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="2754212289804324685">"Profil professionnel"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"Interrompu"</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>
@@ -473,14 +472,10 @@
<string name="interruption_level_none_twoline" msgid="8579382742855486372">"Aucune\ninterruption"</string>
<string name="interruption_level_priority_twoline" msgid="8523482736582498083">"Priorités\nuniquement"</string>
<string name="interruption_level_alarms_twoline" msgid="2045067991335708767">"Alarmes\nuniquement"</string>
- <!-- no translation found for keyguard_indication_charging_time_wireless (577856646141738675) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time (6492711711891071502) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_fast (8390311020603859480) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_slowly (301936949731705417) -->
- <skip />
+ <string name="keyguard_indication_charging_time_wireless" msgid="577856646141738675">"En recharge sans fil : <xliff:g id="PERCENTAGE">%2$s</xliff:g> • Terminée dans <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time" msgid="6492711711891071502">"En recharge : <xliff:g id="PERCENTAGE">%2$s</xliff:g> • Terminée dans <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"En recharge rapide : <xliff:g id="PERCENTAGE">%2$s</xliff:g> • Terminée dans <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"En recharge lente : <xliff:g id="PERCENTAGE">%2$s</xliff:g> • Terminée <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Changer d\'utilisateur"</string>
<string name="accessibility_multi_user_switch_switcher_with_current" msgid="5759855008166759399">"Changer d\'utilisateur (utilisateur actuel <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>)"</string>
<string name="accessibility_multi_user_switch_inactive" msgid="383168614528618402">"Utilisateur actuel : <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -676,12 +671,10 @@
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</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>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Non configuré"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Déverrouiller pour utiliser"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Un problème est survenu lors de la récupération de vos cartes, veuillez réessayer plus tard"</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Paramètres de l\'écran de verrouillage"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Profil professionnel"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Mode Avion"</string>
<string name="add_tile" msgid="6239678623873086686">"Ajouter la tuile"</string>
@@ -871,8 +864,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"Activé"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"Désactivé"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"Non disponible"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"Désactivé"</string>
<string name="nav_bar" msgid="4642708685386136807">"Barre de navigation"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"Disposition"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"Type de bouton gauche supplémentaire"</string>
@@ -1160,4 +1152,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"authentifier"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"accéder à l\'appareil"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Servez-vous de votre empreinte digitale pour ouvrir"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index a9acd50..d7adaba 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Appareil photo"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Téléphoner"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Assistance vocale"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"Déverrouiller"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Appareil verrouillé"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Attente de l\'empreinte digitale"</string>
@@ -289,11 +291,9 @@
<string name="accessibility_quick_settings_hotspot_changed_off" msgid="7002061268910095176">"Point d\'accès mobile désactivé."</string>
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2576895346762408840">"Point d\'accès mobile activé."</string>
<string name="accessibility_casting_turned_off" msgid="1387906158563374962">"Diffusion d\'écran interrompue."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Le mode Travail est en pause."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Mode Travail activé"</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Le mode Travail est en pause."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Le mode Travail est activé."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"L\'économiseur de données est désactivé."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"L\'économiseur de données est activé."</string>
@@ -412,8 +412,7 @@
<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="2754212289804324685">"Profil professionnel"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"En pause"</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>
@@ -672,12 +671,10 @@
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</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>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Non configuré"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Déverrouiller pour utiliser"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Problème de récupération de vos cartes. Réessayez plus tard"</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Paramètres de l\'écran de verrouillage"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Profil professionnel"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Mode Avion"</string>
<string name="add_tile" msgid="6239678623873086686">"Ajouter un bloc"</string>
@@ -867,8 +864,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"Activé"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"Désactivé"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"Indisponible"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"Désactivé"</string>
<string name="nav_bar" msgid="4642708685386136807">"Barre de navigation"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"Disposition"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"Type de bouton gauche supplémentaire"</string>
@@ -1156,4 +1152,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"s\'authentifier"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"accéder à l\'appareil"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Utilisez votre empreinte pour ouvrir"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 083435bf..851c79a 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Cámara"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Teléfono"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Asistente de voz"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"Desbloquear"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Dispositivo bloqueado"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Agardando pola impresión dixital"</string>
@@ -289,11 +291,9 @@
<string name="accessibility_quick_settings_hotspot_changed_off" msgid="7002061268910095176">"Desactivouse a zona wifi móbil."</string>
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2576895346762408840">"Activouse a zona wifi móbil."</string>
<string name="accessibility_casting_turned_off" msgid="1387906158563374962">"Detívose a emisión en pantalla."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Púxose en pausa o modo de traballo."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Modo de traballo activado."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Púxose en pausa o modo de traballo."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Activouse o modo de traballo."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Desactivouse o aforro de datos."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Activouse o aforro de datos."</string>
@@ -412,8 +412,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"Límite de <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"Advertencia <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"Perfil de traballo"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"En pausa"</string>
<string name="quick_settings_night_display_label" msgid="8180030659141778180">"Luz nocturna"</string>
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Activación ao solpor"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"Ata o amencer"</string>
@@ -672,12 +671,10 @@
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</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>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Sen configurar"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Desbloquear para usar"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Produciuse un problema ao obter as tarxetas. Téntao de novo máis tarde"</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Configuración da pantalla de bloqueo"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Perfil de traballo"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Modo avión"</string>
<string name="add_tile" msgid="6239678623873086686">"Engade un atallo"</string>
@@ -867,8 +864,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"Activado"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"Desactivado"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"Non dispoñible"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"Desactivado"</string>
<string name="nav_bar" msgid="4642708685386136807">"Barra de navegación"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"Deseño"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"Tipo de botón adicional á esquerda"</string>
@@ -1156,4 +1152,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"autenticar"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"poñer o dispositivo"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Usa a impresión dixital para abrir"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 99d3af6..167817c 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"કૅમેરો"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"ફોન"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"વૉઇસ સહાય"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"અનલૉક કરો"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"ડિવાઇસ લૉક કરેલું છે"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"ફિંગરપ્રિન્ટની રાહ જોઈ રહ્યાં છીએ"</string>
@@ -292,7 +294,7 @@
<!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
<skip />
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"કાર્ય મોડ ચાલુ."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
+ <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (6422896967647049692) -->
<skip />
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"કાર્ય મોડ ચાલુ કર્યો."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"ડેટા સેવર બંધ કર્યું."</string>
@@ -473,14 +475,10 @@
<string name="interruption_level_none_twoline" msgid="8579382742855486372">"સાવ\nશાંતિ"</string>
<string name="interruption_level_priority_twoline" msgid="8523482736582498083">"ફક્ત\nપ્રાધાન્યતા"</string>
<string name="interruption_level_alarms_twoline" msgid="2045067991335708767">"ફક્ત\nએલાર્મ્સ"</string>
- <!-- no translation found for keyguard_indication_charging_time_wireless (577856646141738675) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time (6492711711891071502) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_fast (8390311020603859480) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_slowly (301936949731705417) -->
- <skip />
+ <string name="keyguard_indication_charging_time_wireless" msgid="577856646141738675">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • વાયરલેસથી ચાર્જ થઈ રહ્યું છે • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>માં ચાર્જ થઈ જશે"</string>
+ <string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ચાર્જ થઈ રહ્યું છે • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>માં ચાર્જ થઈ જશે"</string>
+ <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ઝડપથી ચાર્જ થઈ રહ્યું છે • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>માં ચાર્જ થઈ જશે"</string>
+ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ધીમેથી ચાર્જ થઈ રહ્યું છે • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>માં ચાર્જ થઈ જશે"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"વપરાશકર્તા સ્વિચ કરો"</string>
<string name="accessibility_multi_user_switch_switcher_with_current" msgid="5759855008166759399">"વપરાશકર્તાને સ્વિચ કરો, વર્તમાન વપરાશકર્તા <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_inactive" msgid="383168614528618402">"વર્તમાન વપરાશકર્તા <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -1148,7 +1146,7 @@
<string name="status_before_loading" msgid="1500477307859631381">"ટૂંક સમયમાં કન્ટેન્ટ બતાવવામાં આવશે"</string>
<string name="missed_call" msgid="4228016077700161689">"ચૂકી ગયેલો કૉલ"</string>
<string name="messages_count_overflow_indicator" msgid="7850934067082006043">"<xliff:g id="NUMBER">%d</xliff:g>+"</string>
- <string name="people_tile_description" msgid="8154966188085545556">"તાજેતરના મેસેજ, ચૂકી ગયેલા કૉલ અને સ્ટેટસ અપડેટ જુઓ"</string>
+ <string name="people_tile_description" msgid="8154966188085545556">"તાજેતરના સંદેશા, ચૂકી ગયેલા કૉલ અને સ્ટેટસ અપડેટ જુઓ"</string>
<string name="people_tile_title" msgid="6589377493334871272">"વાતચીત"</string>
<string name="new_notification_text_content_description" msgid="5574393603145263727">"<xliff:g id="NAME">%1$s</xliff:g> દ્વારા કોઈ સંદેશ મોકલવામાં આવ્યો"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> દ્વારા કોઈ છબી મોકલવામાં આવી"</string>
@@ -1160,4 +1158,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"ખાતરી કરો"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"ડિવાઇસ અનલૉક કરો"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"ખોલવા માટે ફિંગરપ્રિન્ટનો ઉપયોગ કરો"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index b526ff6..1160b9f 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"कैमरा"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"फ़ोन"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"आवाज़ से डिवाइस का इस्तेमाल"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"अनलॉक करें"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"डिवाइस लॉक है"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"फ़िंगरप्रिंट का इंतज़ार हो रहा है"</string>
@@ -289,11 +291,9 @@
<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_casting_turned_off" msgid="1387906158563374962">"स्क्रीन कास्ट करना रुक गया."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"वर्क मोड को रोका गया."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"वर्क मोड चालू है."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"वर्क मोड को रोका गया."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"वर्क मोड चालू किया गया."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"डेटा बचाने की सेटिंग बंद कर दी गई है."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"डेटा बचाने की सेटिंग चालू कर दी गई है."</string>
@@ -412,8 +412,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"<xliff:g id="DATA_LIMIT">%s</xliff:g> सीमा"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"<xliff:g id="DATA_LIMIT">%s</xliff:g> चेतावनी"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"वर्क प्रोफ़ाइल"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"रोका गया है"</string>
<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>
@@ -672,12 +671,10 @@
<string name="wallet_title" msgid="5369767670735827105">"वॉलेट"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"सभी दिखाएं"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"पैसे चुकाने के लिए, डिवाइस अनलॉक करें"</string>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"सेट अप नहीं किया गया है"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"इस्तेमाल करने के लिए, डिवाइस अनलॉक करें"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"आपके कार्ड की जानकारी पाने में कोई समस्या हुई है. कृपया बाद में कोशिश करें"</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"लॉक स्क्रीन की सेटिंग"</string>
<string name="status_bar_work" msgid="5238641949837091056">"वर्क प्रोफ़ाइल"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"हवाई जहाज़ मोड"</string>
<string name="add_tile" msgid="6239678623873086686">"टाइल जोड़ें"</string>
@@ -867,8 +864,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"चालू"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"बंद"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"उपलब्ध नहीं है"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"बंद है"</string>
<string name="nav_bar" msgid="4642708685386136807">"नेविगेशन बार"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"लेआउट"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"कुछ और बाएं बटन के प्रकार"</string>
@@ -1119,7 +1115,7 @@
<string name="basic_status" msgid="2315371112182658176">"ऐसी बातचीत जिसमें इंटरैक्शन डेटा मौजूद नहीं है"</string>
<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="no_conversations_text" msgid="7362374212649891057">"नए मैसेज आने पर यहां देखें"</string>
<string name="priority_conversations" msgid="3967482288896653039">"अहम बातचीत"</string>
<string name="recent_conversations" msgid="8531874684782574622">"हाल ही में की गई बातचीत"</string>
<string name="okay" msgid="6490552955618608554">"ठीक है"</string>
@@ -1156,4 +1152,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"पुष्टि करें"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"डिवाइस की होम स्क्रीन पर जाएं"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"खोलने के लिए, फ़िंगरप्रिंट का इस्तेमाल करें"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index fedeb77..672b7db 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Fotoaparat"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Telefon"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Glasovna pomoć"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"Otključavanje"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Uređaj je zaključan"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Čekanje na otisak prsta"</string>
@@ -289,11 +291,9 @@
<string name="accessibility_quick_settings_hotspot_changed_off" msgid="7002061268910095176">"Mobilna žarišna točka isključena."</string>
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2576895346762408840">"Mobilna žarišna točka uključena."</string>
<string name="accessibility_casting_turned_off" msgid="1387906158563374962">"Emitiranje zaslona zaustavljeno."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Poslovni je način pauziran."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Način rada uključen."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Poslovni je način pauziran."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Način rada uključen."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Štednja podatkovnog prometa isključena."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Štednja podatkovnog prometa uključena."</string>
@@ -414,8 +414,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"Ograničenje od <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"Upozorenje <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"Poslovni profil"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"Pauzirano"</string>
<string name="quick_settings_night_display_label" msgid="8180030659141778180">"Noćno svjetlo"</string>
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Uključuje se u suton"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"Do izlaska sunca"</string>
@@ -675,12 +674,10 @@
<string name="wallet_title" msgid="5369767670735827105">"Novčanik"</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>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Nije postavljeno"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Otključajte da biste koristili"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Pojavio se problem prilikom dohvaćanja kartica, pokušajte ponovo kasnije"</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Postavke zaključanog zaslona"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Poslovni profil"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Način rada u zrakoplovu"</string>
<string name="add_tile" msgid="6239678623873086686">"Dodavanje pločice"</string>
@@ -872,8 +869,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"Uključeno"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"Isključeno"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"Nedostupno"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"Onemogućeno"</string>
<string name="nav_bar" msgid="4642708685386136807">"Navigacijska traka"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"Izgled"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"Vrsta dodatnog lijevog gumba"</string>
@@ -1162,4 +1158,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"autentificirali"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"pristupili uređaju"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Otvorite pomoću otiska prsta"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index d3bd516..b17d040 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Kamera"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Telefon"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Hangsegéd"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"Feloldás"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Az eszköz zárolva van"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Várakozás az ujjlenyomatra"</string>
@@ -289,11 +291,9 @@
<string name="accessibility_quick_settings_hotspot_changed_off" msgid="7002061268910095176">"A mobil hotspot kikapcsolva."</string>
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2576895346762408840">"A mobil hotspot bekapcsolva."</string>
<string name="accessibility_casting_turned_off" msgid="1387906158563374962">"A képernyő átküldése leállítva."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Munkahelyi mód szüneteltetve."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Munka mód be."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Munkahelyi mód szüneteltetve."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Munka mód bekapcsolva."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Adatforgalom-csökkentő kikapcsolva."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Adatforgalom-csökkentő bekapcsolva."</string>
@@ -412,8 +412,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"<xliff:g id="DATA_LIMIT">%s</xliff:g> korlát"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"Figyelem! <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"Munkaprofil"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"Szünetel"</string>
<string name="quick_settings_night_display_label" msgid="8180030659141778180">"Éjszakai fény"</string>
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Be: naplemente"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"Napfelkeltéig"</string>
@@ -672,12 +671,10 @@
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</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>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Nincs beállítva"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Oldja fel a használathoz"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Probléma merült fel a kártyák lekérésekor, próbálja újra később"</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Lezárási képernyő beállításai"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Munkahelyi profil"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Repülős üzemmód"</string>
<string name="add_tile" msgid="6239678623873086686">"Mozaik hozzáadása"</string>
@@ -867,8 +864,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"Be"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"Ki"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"Nem használható"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"Kikapcsolva"</string>
<string name="nav_bar" msgid="4642708685386136807">"Navigációs sáv"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"Elrendezés"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"További bal oldali gombtípus"</string>
@@ -1156,4 +1152,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"a hitelesítéshez"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"eszköz megadásához"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Ujjlenyomat használata a megnyitáshoz"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index ad11a26..61ed6e6 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Տեսախցիկ"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Հեռախոս"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Ձայնային հուշումներ"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"Ապակողպել"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Սարքը կողպված է"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Մատնահետքի սպասում"</string>
@@ -289,11 +291,9 @@
<string name="accessibility_quick_settings_hotspot_changed_off" msgid="7002061268910095176">"Շարժական կապի WiFi ցրիչն անջատվեց:"</string>
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2576895346762408840">"Շարժական կապի WiFi ցրիչը միացավ:"</string>
<string name="accessibility_casting_turned_off" msgid="1387906158563374962">"Էկրանի հեռարձակումն ընդհատվեց:"</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Աշխատանքային ռեժիմի աշխատանքը դադարեցված է։"</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Աշխատանքային ռեժիմը միացված է:"</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Աշխատանքային ռեժիմը դադարեցված է։"</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Աշխատանքային ռեժիմը միացվեց:"</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Տվյալների խնայումն անջատվեց:"</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Թրաֆիկի տնտեսումը միացվեց:"</string>
@@ -412,8 +412,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"Սահմանաչափ՝ <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"<xliff:g id="DATA_LIMIT">%s</xliff:g> զգուշացում"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"Աշխատանքային պրոֆիլ"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"Դադարեցված է"</string>
<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>
@@ -473,14 +472,10 @@
<string name="interruption_level_none_twoline" msgid="8579382742855486372">"Ընդհանուր\nլուռ վիճակը"</string>
<string name="interruption_level_priority_twoline" msgid="8523482736582498083">"Միայն\nկարևորները"</string>
<string name="interruption_level_alarms_twoline" msgid="2045067991335708767">"Միայն\nզարթուցիչ"</string>
- <!-- no translation found for keyguard_indication_charging_time_wireless (577856646141738675) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time (6492711711891071502) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_fast (8390311020603859480) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_slowly (301936949731705417) -->
- <skip />
+ <string name="keyguard_indication_charging_time_wireless" msgid="577856646141738675">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Անլար լիցքավորում • Մնացել է <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Լիցքավորում • Մնացել է <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Արագ լիցքավորում • Մնացել է <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Դանդաղ լիցքավորում • Մնացել է <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Անջատել օգտվողին"</string>
<string name="accessibility_multi_user_switch_switcher_with_current" msgid="5759855008166759399">"Փոխել օգտատիրոջը. ներկայիս օգտատերն է՝ <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_inactive" msgid="383168614528618402">"Ընթացիկ օգտատերը՝ <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -676,12 +671,10 @@
<string name="wallet_title" msgid="5369767670735827105">"Դրամապանակ"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Ցույց տալ բոլորը"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Ապակողպել՝ վճարելու համար"</string>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Կարգավորված չէ"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Ապակողպել՝ օգտագործելու համար"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Չհաջողվեց բեռնել քարտերը։ Նորից փորձեք։"</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Կողպէկրանի կարգավորումներ"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Android for Work-ի պրոֆիլ"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Ավիառեժիմ"</string>
<string name="add_tile" msgid="6239678623873086686">"Սալիկի ավելացում"</string>
@@ -871,8 +864,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"Միացված է"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"Անջատված է"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"Հասանելի չէ"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"Անջատված է"</string>
<string name="nav_bar" msgid="4642708685386136807">"Նավիգացիայի գոտի"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"Դասավորություն"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"Լրացուցիչ ձախ կոճակի տեսակ"</string>
@@ -1123,7 +1115,7 @@
<string name="basic_status" msgid="2315371112182658176">"Բաց զրույց"</string>
<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="no_conversations_text" msgid="7362374212649891057">"Վերադարձեք այստեղ, երբ հաղորդագրություններ ստանաք"</string>
<string name="priority_conversations" msgid="3967482288896653039">"Կարևոր զրույցներ"</string>
<string name="recent_conversations" msgid="8531874684782574622">"Վերջին հաղորդագրությունները"</string>
<string name="okay" msgid="6490552955618608554">"Եղավ"</string>
@@ -1160,4 +1152,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"նույնականացնել"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"նշել սարքը"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Բացելու համար օգտագործեք մատնահետքը"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 1e67b9a..880ca64 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Kamera"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Telepon"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Bantuan Suara"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"Buka kunci"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Perangkat terkunci"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Menunggu sidik jari"</string>
@@ -289,11 +291,9 @@
<string name="accessibility_quick_settings_hotspot_changed_off" msgid="7002061268910095176">"Hotspot seluler dinonaktifkan."</string>
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2576895346762408840">"Hotspot seluler diaktifkan."</string>
<string name="accessibility_casting_turned_off" msgid="1387906158563374962">"Transmisi layar berhenti."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Mode kerja dijeda."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Mode kerja aktif."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Mode kerja dijeda."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Mode kerja diaktifkan."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Penghemat Data nonaktif."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Penghemat Data diaktifkan."</string>
@@ -412,8 +412,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"Batas <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"Peringatan <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"Profil kerja"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"Dijeda"</string>
<string name="quick_settings_night_display_label" msgid="8180030659141778180">"Cahaya Malam"</string>
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Aktif saat malam"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"Sampai pagi"</string>
@@ -473,14 +472,10 @@
<string name="interruption_level_none_twoline" msgid="8579382742855486372">"Senyap\ntotal"</string>
<string name="interruption_level_priority_twoline" msgid="8523482736582498083">"Hanya\nprioritas"</string>
<string name="interruption_level_alarms_twoline" msgid="2045067991335708767">"Hanya\nalarm"</string>
- <!-- no translation found for keyguard_indication_charging_time_wireless (577856646141738675) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time (6492711711891071502) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_fast (8390311020603859480) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_slowly (301936949731705417) -->
- <skip />
+ <string name="keyguard_indication_charging_time_wireless" msgid="577856646141738675">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengisi daya secara nirkabel • Penuh dalam waktu <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengisi daya • Penuh dalam waktu <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengisi daya dengan cepat • Penuh dalam waktu <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengisi daya dengan lambat • Penuh dalam waktu <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Beralih pengguna"</string>
<string name="accessibility_multi_user_switch_switcher_with_current" msgid="5759855008166759399">"Ganti pengguna, pengguna saat ini <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_inactive" msgid="383168614528618402">"Pengguna saat ini <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -676,12 +671,10 @@
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</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>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Belum disiapkan"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Buka kunci untuk menggunakan"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Terjadi masalah saat mendapatkan kartu Anda, coba lagi nanti"</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Setelan layar kunci"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Profil kerja"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Mode pesawat"</string>
<string name="add_tile" msgid="6239678623873086686">"Tambahkan ubin"</string>
@@ -871,8 +864,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"Aktif"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"Nonaktif"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"Tidak tersedia"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"Nonaktif"</string>
<string name="nav_bar" msgid="4642708685386136807">"Bilah navigasi"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"Tata Letak"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"Jenis tombol ekstra kiri"</string>
@@ -1148,7 +1140,7 @@
<string name="status_before_loading" msgid="1500477307859631381">"Konten akan segera muncul"</string>
<string name="missed_call" msgid="4228016077700161689">"Panggilan tak terjawab"</string>
<string name="messages_count_overflow_indicator" msgid="7850934067082006043">"<xliff:g id="NUMBER">%d</xliff:g>+"</string>
- <string name="people_tile_description" msgid="8154966188085545556">"Melihat pesan terbaru, panggilan tak terjawab, dan pembaruan status"</string>
+ <string name="people_tile_description" msgid="8154966188085545556">"Lihat pesan terbaru, panggilan tak terjawab, dan pembaruan status"</string>
<string name="people_tile_title" msgid="6589377493334871272">"Percakapan"</string>
<string name="new_notification_text_content_description" msgid="5574393603145263727">"<xliff:g id="NAME">%1$s</xliff:g> mengirim pesan"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> mengirim gambar"</string>
@@ -1160,4 +1152,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"autentikasi"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"masukkan perangkat"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Gunakan sidik jari untuk membuka"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 22feecfc..eb7e4ec 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Myndavél"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Sími"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Raddaðstoð"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"Taka úr lás"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Tækið er læst"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Bíður eftir fingrafari"</string>
@@ -289,11 +291,9 @@
<string name="accessibility_quick_settings_hotspot_changed_off" msgid="7002061268910095176">"Slökkt á farsímaaðgangsstað."</string>
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2576895346762408840">"Kveikt á farsímaaðgangsstað."</string>
<string name="accessibility_casting_turned_off" msgid="1387906158563374962">"Skjáútsendingu hætt."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Hlé gert á vinnustillingu."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Kveikt á vinnustillingu."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Hlé gert á vinnustillingu."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Kveikt á vinnustillingu."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Slökkt var á gagnasparnaði."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Kveikt var á gagnasparnaði."</string>
@@ -412,8 +412,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"<xliff:g id="DATA_LIMIT">%s</xliff:g> hámark"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"<xliff:g id="DATA_LIMIT">%s</xliff:g> viðvörun"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"Vinnusnið"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"Hlé"</string>
<string name="quick_settings_night_display_label" msgid="8180030659141778180">"Næturljós"</string>
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Kveikt við sólsetur"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"Til sólarupprásar"</string>
@@ -672,12 +671,10 @@
<string name="wallet_title" msgid="5369767670735827105">"Veski"</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>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Ekki uppsett"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Taktu úr lás til að nota"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Vandamál kom upp við að sækja kortin þín. Reyndu aftur síðar"</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Stillingar fyrir læstan skjá"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Vinnusnið"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Flugstilling"</string>
<string name="add_tile" msgid="6239678623873086686">"Bæta reit við"</string>
@@ -867,8 +864,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"Kveikt"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"Slökkt"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"Ekki í boði"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"Slökkt"</string>
<string name="nav_bar" msgid="4642708685386136807">"Yfirlitsstika"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"Útlit"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"Gerð aukahnapps til vinstri"</string>
@@ -1156,4 +1152,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"auðkenna"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"opna tæki"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Opna með fingrafari"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 6cc699b..600d8b7 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -136,6 +136,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Fotocamera"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Telefono"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Voice Assist"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"Sblocca"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Dispositivo bloccato"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"In attesa dell\'impronta"</string>
@@ -289,11 +290,9 @@
<string name="accessibility_quick_settings_hotspot_changed_off" msgid="7002061268910095176">"Hotspot mobile disattivato."</string>
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2576895346762408840">"Hotspot mobile attivato."</string>
<string name="accessibility_casting_turned_off" msgid="1387906158563374962">"Trasmissione dello schermo interrotta."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Modalità Lavoro in pausa."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Modalità Lavoro attiva."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Modalità Lavoro messa in pausa."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Modalità Lavoro attivata."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Funzione Risparmio dati disattivata."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Funzione Risparmio dati attivata."</string>
@@ -412,8 +411,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"Limite di <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"Avviso <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"Profilo di lavoro"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"In pausa"</string>
<string name="quick_settings_night_display_label" msgid="8180030659141778180">"Luminosità notturna"</string>
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Attivata al tramonto"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"Fino all\'alba"</string>
@@ -672,12 +670,10 @@
<string name="wallet_title" msgid="5369767670735827105">"Portafoglio"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Espandi"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Sblocca per pagare"</string>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Nessuna configurazione"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Sblocca per usare"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Si è verificato un problema durante il recupero delle tue carte. Riprova più tardi."</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Impostazioni schermata di blocco"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Profilo di lavoro"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Modalità aereo"</string>
<string name="add_tile" msgid="6239678623873086686">"Aggiungi riquadro"</string>
@@ -867,8 +863,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"On"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"Off"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"Non disponibile"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"Riquadro disattivato"</string>
<string name="nav_bar" msgid="4642708685386136807">"Barra di navigazione"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"Layout"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"Tipo di pulsante extra sinistra"</string>
@@ -1119,7 +1114,7 @@
<string name="basic_status" msgid="2315371112182658176">"Apri conversazione"</string>
<string name="select_conversation_title" msgid="6716364118095089519">"Widget di conversazione"</string>
<string name="select_conversation_text" msgid="3376048251434956013">"Tocca una conversazione per aggiungerla alla schermata Home"</string>
- <string name="no_conversations_text" msgid="7362374212649891057">"Torna qui dopo aver ricevuto qualche messaggio"</string>
+ <string name="no_conversations_text" msgid="7362374212649891057">"Torna qui quando avrai ricevuto qualche messaggio"</string>
<string name="priority_conversations" msgid="3967482288896653039">"Conversazioni prioritarie"</string>
<string name="recent_conversations" msgid="8531874684782574622">"Conversazioni recenti"</string>
<string name="okay" msgid="6490552955618608554">"OK"</string>
@@ -1156,4 +1151,6 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"effettuare l\'autenticazione"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"accedere al dispositivo"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Usa l\'impronta per aprire"</string>
+ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autenticazione obbligatoria. Eseguila toccando il sensore di impronte digitali."</string>
+ <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Telefonata in corso"</string>
</resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 1853ecf..c9be358 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -136,6 +136,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"מצלמה"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"טלפון"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"האסיסטנט"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"ארנק"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"ביטול נעילה"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"המכשיר נעול"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"בהמתנה לטביעת אצבע"</string>
@@ -289,11 +290,9 @@
<string name="accessibility_quick_settings_hotspot_changed_off" msgid="7002061268910095176">"נקודת האינטרנט (hotspot) כבויה."</string>
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2576895346762408840">"נקודת האינטרנט (hotspot) מופעלת."</string>
<string name="accessibility_casting_turned_off" msgid="1387906158563374962">"העברת המסך הופסקה."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"מצב העבודה הושהה."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"מצב עבודה מופעל."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"מצב העבודה הושהה."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"מצב עבודה הופעל."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"חוסך הנתונים (Data Saver) כובה."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"חוסך הנתונים (Data Saver) הופעל."</string>
@@ -416,8 +415,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"הגבלה של <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"אזהרה – <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"פרופיל עבודה"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"בהשהיה"</string>
<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>
@@ -477,14 +475,10 @@
<string name="interruption_level_none_twoline" msgid="8579382742855486372">"שקט\nמוחלט"</string>
<string name="interruption_level_priority_twoline" msgid="8523482736582498083">"הודעות בעדיפות\nבלבד"</string>
<string name="interruption_level_alarms_twoline" msgid="2045067991335708767">"התראות\nבלבד"</string>
- <!-- no translation found for keyguard_indication_charging_time_wireless (577856646141738675) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time (6492711711891071502) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_fast (8390311020603859480) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_slowly (301936949731705417) -->
- <skip />
+ <string name="keyguard_indication_charging_time_wireless" msgid="577856646141738675">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • בטעינה אלחוטית • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> עד לסיום"</string>
+ <string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • בטעינה • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> עד לסיום"</string>
+ <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • בטעינה מהירה • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> עד לסיום"</string>
+ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • בטעינה איטית • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> עד לסיום"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"החלפת משתמש"</string>
<string name="accessibility_multi_user_switch_switcher_with_current" msgid="5759855008166759399">"החלפת משתמש. המשתמש הנוכחי: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_inactive" msgid="383168614528618402">"משתמש נוכחי <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -682,12 +676,10 @@
<string name="wallet_title" msgid="5369767670735827105">"ארנק"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"הצגת הכול"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"לביטול הנעילה ולתשלום"</string>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"לא מוגדר"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"יש לבטל את הנעילה כדי להשתמש"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"הייתה בעיה בקבלת הכרטיסים שלך. כדאי לנסות שוב מאוחר יותר"</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"הגדרות מסך הנעילה"</string>
<string name="status_bar_work" msgid="5238641949837091056">"פרופיל עבודה"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"מצב טיסה"</string>
<string name="add_tile" msgid="6239678623873086686">"הוספת אריח"</string>
@@ -881,8 +873,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"פועל"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"כבוי"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"לא זמין"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"מושבת"</string>
<string name="nav_bar" msgid="4642708685386136807">"סרגל ניווט"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"פריסה"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"סוג נוסף של לחצן שמאלי"</string>
@@ -1172,4 +1163,6 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"אימות"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"הזנת מכשיר"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"שימוש בטביעת אצבע כדי לפתוח"</string>
+ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"נדרש אימות. יש לגעת בחיישן טביעות האצבע כדי לבצע אימות."</string>
+ <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"מתקיימת שיחה"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 0e331de..6465b44 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"カメラ"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"電話"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"音声アシスト"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"ロック解除"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"デバイスはロックされています"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"指紋を待っています"</string>
@@ -289,11 +291,9 @@
<string name="accessibility_quick_settings_hotspot_changed_off" msgid="7002061268910095176">"モバイルアクセスポイントをOFFにしました。"</string>
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2576895346762408840">"モバイルアクセスポイントをONにしました。"</string>
<string name="accessibility_casting_turned_off" msgid="1387906158563374962">"画面のキャストが停止しました。"</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Work モードを OFF にしました。"</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Work モードがオンです。"</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Workモードを一時停止しました。"</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Work モードをオンにしました。"</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"データセーバーが OFF になりました。"</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"データセーバーが ON になりました。"</string>
@@ -412,8 +412,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"上限: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"警告: 上限は<xliff:g id="DATA_LIMIT">%s</xliff:g>です"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"仕事用プロファイル"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"OFF"</string>
<string name="quick_settings_night_display_label" msgid="8180030659141778180">"夜間モード"</string>
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"日の入りに ON"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"日の出まで"</string>
@@ -672,12 +671,10 @@
<string name="wallet_title" msgid="5369767670735827105">"ウォレット"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"すべて表示"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"ロックを解除して支払う"</string>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"未設定"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ロックを解除して使用"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"カードの取得中に問題が発生しました。しばらくしてからもう一度お試しください"</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"ロック画面の設定"</string>
<string name="status_bar_work" msgid="5238641949837091056">"仕事用プロファイル"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"機内モード"</string>
<string name="add_tile" msgid="6239678623873086686">"タイルを追加"</string>
@@ -867,8 +864,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"ON"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"OFF"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"使用不可"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"無効"</string>
<string name="nav_bar" msgid="4642708685386136807">"ナビゲーション バー"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"レイアウト"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"その他の左ボタンタイプ"</string>
@@ -1119,7 +1115,7 @@
<string name="basic_status" msgid="2315371112182658176">"空の会話"</string>
<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="no_conversations_text" msgid="7362374212649891057">"メッセージを受信すると、ここに表示されます"</string>
<string name="priority_conversations" msgid="3967482288896653039">"優先度の高い会話"</string>
<string name="recent_conversations" msgid="8531874684782574622">"最近の会話"</string>
<string name="okay" msgid="6490552955618608554">"OK"</string>
@@ -1156,4 +1152,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"認証"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"デバイスを入力"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"指紋を使って開いてください"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index 2d4d9bc..63205e3 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -136,6 +136,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"კამერა"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"ტელეფონი"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"ხმოვანი დახმარება"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"განბლოკვა"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"მოწყობილობა ჩაკეტილია"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"თითის ანაბეჭდის მოლოდინში"</string>
@@ -289,11 +290,9 @@
<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_casting_turned_off" msgid="1387906158563374962">"ეკრანის გადაცემა შეჩერებულია."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"სამსახურის რეჟიმი დაპაუზებულია."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"სამსახურის რეჟიმი ჩართულია."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"სამსახურის რეჟიმი დაპაუზებულია."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"სამსახურის რეჟიმი ჩართულია."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"მონაცემთა დამზოგველი გამორთულია."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"მონაცემთა დამზოგველი ჩართულია."</string>
@@ -412,8 +411,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"ლიმიტი: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"<xliff:g id="DATA_LIMIT">%s</xliff:g> გაფრთხილება"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"სამსახურის პროფილი"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"დაპაუზებულია"</string>
<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>
@@ -473,14 +471,10 @@
<string name="interruption_level_none_twoline" msgid="8579382742855486372">"სრული\nსიჩუმე"</string>
<string name="interruption_level_priority_twoline" msgid="8523482736582498083">"მხოლოდ\nპრიორიტეტულები"</string>
<string name="interruption_level_alarms_twoline" msgid="2045067991335708767">"მხოლოდ\nგაფრთხილებები"</string>
- <!-- no translation found for keyguard_indication_charging_time_wireless (577856646141738675) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time (6492711711891071502) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_fast (8390311020603859480) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_slowly (301936949731705417) -->
- <skip />
+ <string name="keyguard_indication_charging_time_wireless" msgid="577856646141738675">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • უსადენოდ იტენება • სრულ დატენვამდე <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • იტენება • სრულ დატენვამდე <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • სწრაფად იტენება • სრულ დატენვამდე <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ნელა იტენება • სრულ დატენვამდე <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"მომხმარებლის გადართვა"</string>
<string name="accessibility_multi_user_switch_switcher_with_current" msgid="5759855008166759399">"მომხმარებლის გდართვა. ამჟამინდელი მომხმარებელი <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_inactive" msgid="383168614528618402">"ამჟამინდელი მომხმარებელი <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -676,12 +670,10 @@
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"ყველას ჩვენება"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"გადასახდელად განბლოკვა"</string>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"არ არის დაყენებული"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"გამოსაყენებლად განბლოკვა"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"თქვენი ბარათების მიღებისას პრობლემა წარმოიშვა. ცადეთ ხელახლა მოგვიანებით"</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"ჩაკეტილი ეკრანის პარამეტრები"</string>
<string name="status_bar_work" msgid="5238641949837091056">"სამსახურის პროფილი"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"თვითმფრინავის რეჟიმი"</string>
<string name="add_tile" msgid="6239678623873086686">"მოზაიკის დამატება"</string>
@@ -871,8 +863,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"ჩართული"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"გამორთვა"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"მიუწვდომელი"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"გათიშულია"</string>
<string name="nav_bar" msgid="4642708685386136807">"ნავიგაციის ზოლი"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"განლაგება"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"მარცხენა დამატებითი ღილაკის ტიპი"</string>
@@ -1127,9 +1118,9 @@
<string name="priority_conversations" msgid="3967482288896653039">"პრიორიტეტული საუბრები"</string>
<string name="recent_conversations" msgid="8531874684782574622">"ბოლო მიმოწერები"</string>
<string name="okay" msgid="6490552955618608554">"კარგი"</string>
- <string name="timestamp" msgid="6577851592534538533">"<xliff:g id="DURATION">%1$s</xliff:g>-ს წინ"</string>
+ <string name="timestamp" msgid="6577851592534538533">"<xliff:g id="DURATION">%1$s</xliff:g>ს წინ"</string>
<string name="less_than_timestamp" msgid="6598972791137724517">"<xliff:g id="DURATION">%1$s</xliff:g>-ზე ნაკლები ხნის წინ"</string>
- <string name="over_timestamp" msgid="4765793502859358634">"<xliff:g id="DURATION">%1$s</xliff:g>-ზე მეტი ხნის წინ"</string>
+ <string name="over_timestamp" msgid="4765793502859358634">"<xliff:g id="DURATION">%1$s</xliff:g>ზე მეტი ხნის წინ"</string>
<string name="birthday_status" msgid="2596961629465396761">"დაბადების დღე"</string>
<string name="birthday_status_content_description" msgid="682836371128282925">"<xliff:g id="NAME">%1$s</xliff:g> დღეს იუბილარია"</string>
<string name="upcoming_birthday_status" msgid="2005452239256870351">"მალე დაბადების დღეა"</string>
@@ -1160,4 +1151,6 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"ავტორიზაცია"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"მოწყობილობის შეყვანა"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"გასახსნელად გამოიყენეთ თითის ანაბეჭდი"</string>
+ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"საჭიროა ავტორიზაცია. ავტორიზაციისთვის შეეხეთ თითის ანაბეჭდის სენსორს."</string>
+ <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"მიმდინარე სატელეფონო ზარი"</string>
</resources>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index a4cfaaa..bb5d51f 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Камера"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Телефон"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Дауыс көмекшісі"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"Бекітпесін ашу"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Құрылғы құлыпталды."</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Саусақ ізі күтілуде"</string>
@@ -289,11 +291,9 @@
<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_casting_turned_off" msgid="1387906158563374962">"Экранды трансляциялау тоқтатылды."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Жұмыс режимі кідіртілді."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Жұмыс режимі қосулы."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Жұмыс режимі кідіртілді."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Жұмыс режимі қосылды."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Трафикті үнемдеу режимі өшірілді."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Трафикті үнемдеу режимі қосылды."</string>
@@ -412,8 +412,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"<xliff:g id="DATA_LIMIT">%s</xliff:g> шегі"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"<xliff:g id="DATA_LIMIT">%s</xliff:g> туралы ескерту"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"Жұмыс профилі"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"Кідіртілген"</string>
<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>
@@ -473,14 +472,10 @@
<string name="interruption_level_none_twoline" msgid="8579382742855486372">"Толық\nтыныштық"</string>
<string name="interruption_level_priority_twoline" msgid="8523482736582498083">"Тек\nбасымдық"</string>
<string name="interruption_level_alarms_twoline" msgid="2045067991335708767">"Тек\nдабылдар"</string>
- <!-- no translation found for keyguard_indication_charging_time_wireless (577856646141738675) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time (6492711711891071502) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_fast (8390311020603859480) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_slowly (301936949731705417) -->
- <skip />
+ <string name="keyguard_indication_charging_time_wireless" msgid="577856646141738675">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Сымсыз зарядталуда • Толуына <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> қалды."</string>
+ <string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Зарядталуда • Толуына <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> қалды."</string>
+ <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Жылдам зарядталуда • Толуына <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> қалды."</string>
+ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Баяу зарядталуда • Толуына <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> қалды."</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Пайдаланушыны ауыстыру"</string>
<string name="accessibility_multi_user_switch_switcher_with_current" msgid="5759855008166759399">"Пайдаланушыны ауыстыру, ағымдағы пайдаланушы <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_inactive" msgid="383168614528618402">"Ағымдағы пайдаланушы: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -676,12 +671,10 @@
<string name="wallet_title" msgid="5369767670735827105">"Әмиян"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Барлығын көрсету"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Төлеу үшін құлыпты ашу"</string>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Реттелмеген"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Пайдалану үшін құлыпты ашу"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Карталарыңыз алынбады, кейінірек қайталап көріңіз."</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Экран құлпының параметрлері"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Жұмыс профилі"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Ұшақ режимі"</string>
<string name="add_tile" msgid="6239678623873086686">"Тақтайша қосу"</string>
@@ -871,8 +864,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"Қосулы"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"Өшірулі"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"Қолжетімді емес"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"Өшірілген"</string>
<string name="nav_bar" msgid="4642708685386136807">"Шарлау тақтасы"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"Формат"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"Қосымша сол жақ түйме түрі"</string>
@@ -1124,8 +1116,8 @@
<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="recent_conversations" msgid="8531874684782574622">"Соңғы чаттар"</string>
+ <string name="priority_conversations" msgid="3967482288896653039">"Маңызды әңгімелер"</string>
+ <string name="recent_conversations" msgid="8531874684782574622">"Соңғы әңгімелер"</string>
<string name="okay" msgid="6490552955618608554">"Жарайды"</string>
<string name="timestamp" msgid="6577851592534538533">"<xliff:g id="DURATION">%1$s</xliff:g> бұрын"</string>
<string name="less_than_timestamp" msgid="6598972791137724517">"Максимум <xliff:g id="DURATION">%1$s</xliff:g> бұрын"</string>
@@ -1160,4 +1152,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"аутентификациялау"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"құрылғыны енгізу"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Ашу үшін саусақ ізін пайдаланыңыз."</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index fddf305..ed7bbe9 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"ម៉ាស៊ីនថត"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"ទូរសព្ទ"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"ជំនួយសំឡេង"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"ដោះសោ"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"បានចាក់សោឧបករណ៍"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"កំពុងរង់ចាំស្នាមម្រាមដៃ"</string>
@@ -289,11 +291,9 @@
<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_casting_turned_off" msgid="1387906158563374962">"បានបញ្ឈប់ការចាត់ថ្នាក់អេក្រង់។"</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"បានផ្អាកមុខងារការងារ។"</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"បើករបៀបការងារ"</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"បានផ្អាកមុខងារការងារ។"</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"បានបើករបៀបការងារ"</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"បានបិទកម្មវិធីសន្សំសំចៃទិន្នន័យ"</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"បានបើកកម្មវិធីសន្សំសំចៃទិន្នន័យ"</string>
@@ -412,8 +412,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"ដែនកំណត់ <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"<xliff:g id="DATA_LIMIT">%s</xliff:g> ការព្រមាន"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"កម្រងព័ត៌មានការងារ"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"បានផ្អាក"</string>
<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>
@@ -672,12 +671,10 @@
<string name="wallet_title" msgid="5369767670735827105">"កាបូប"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"បង្ហាញទាំងអស់"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"ដោះសោដើម្បីបង់ប្រាក់"</string>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"មិនបានរៀបចំទេ"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ដោះសោដើម្បីប្រើប្រាស់"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"មានបញ្ហាក្នុងការទាញយកកាតរបស់អ្នក សូមព្យាយាមម្ដងទៀតនៅពេលក្រោយ"</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"ការកំណត់អេក្រង់ចាក់សោ"</string>
<string name="status_bar_work" msgid="5238641949837091056">"ប្រវត្តិរូបការងារ"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"ពេលជិះយន្តហោះ"</string>
<string name="add_tile" msgid="6239678623873086686">"បន្ថែមក្រឡាល្អិត"</string>
@@ -867,8 +864,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"បើក"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"បិទ"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"មិនមាន"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"បានបិទ"</string>
<string name="nav_bar" msgid="4642708685386136807">"របាររុករក"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"ប្លង់"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"ប្រភេទប៊ូតុងខាងឆ្វេងបន្ថែម"</string>
@@ -1156,4 +1152,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"ផ្ទៀងផ្ទាត់"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"បញ្ចូលឧបករណ៍"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"ប្រើស្នាមម្រាមដៃ ដើម្បីបើក"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 8d542ddf..cef9e3f 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"ಕ್ಯಾಮರಾ"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"ಫೋನ್"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"ಧ್ವನಿ ಸಹಾಯಕ"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"ಅನ್ಲಾಕ್"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"ಸಾಧನ ಲಾಕ್ ಆಗಿದೆ"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"ಫಿಂಗರ್ಪ್ರಿಂಟ್ಗಾಗಿ ನಿರೀಕ್ಷಿಸಲಾಗುತ್ತಿದೆ"</string>
@@ -291,7 +293,7 @@
<string name="accessibility_casting_turned_off" msgid="1387906158563374962">"ಸ್ಕ್ರೀನ್ ಪ್ರಸಾರವನ್ನು ನಿಲ್ಲಿಸಲಾಗಿದೆ."</string>
<string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"ಕೆಲಸದ ಮೋಡ್ ವಿರಾಮಗೊಳಿಸಲಾಗಿದೆ."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"ಕೆಲಸದ ಮೋಡ್ ಆನ್ ಆಗಿದೆ."</string>
- <string name="accessibility_quick_settings_work_mode_changed_off" msgid="2653550342355027441">"ಕೆಲಸದ ಮೋಡ್ ಅನ್ನು ವಿರಾಮಗೊಳಿಸಲಾಗಿದೆ."</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>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"ಡೇಟಾ ಸೇವರ್ ಆಫ್ ಮಾಡಲಾಗಿದೆ."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"ಡೇಟಾ ಸೇವರ್ ಆನ್ ಮಾಡಲಾಗಿದೆ."</string>
@@ -470,14 +472,10 @@
<string name="interruption_level_none_twoline" msgid="8579382742855486372">"ಸಂಪೂರ್ಣ\nನಿಶ್ಯಬ್ಧ"</string>
<string name="interruption_level_priority_twoline" msgid="8523482736582498083">"ಆದ್ಯತೆ\nಮಾತ್ರ"</string>
<string name="interruption_level_alarms_twoline" msgid="2045067991335708767">"ಅಲಾರಮ್ಗಳು\nಮಾತ್ರ"</string>
- <!-- no translation found for keyguard_indication_charging_time_wireless (577856646141738675) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time (6492711711891071502) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_fast (8390311020603859480) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_slowly (301936949731705417) -->
- <skip />
+ <string name="keyguard_indication_charging_time_wireless" msgid="577856646141738675">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ವೈರ್ಲೆಸ್ ಆಗಿ ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ಸಮಯದಲ್ಲಿ ಪೂರ್ಣಗೊಳ್ಳುತ್ತದೆ"</string>
+ <string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ಸಮಯದಲ್ಲಿ ಪೂರ್ಣಗೊಳ್ಳುತ್ತದೆ"</string>
+ <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ವೇಗವಾಗಿ ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ಸಮಯದಲ್ಲಿ ಪೂರ್ಣಗೊಳ್ಳುತ್ತದೆ"</string>
+ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ನಿಧಾನವಾಗಿ ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ಸಮಯದಲ್ಲಿ ಪೂರ್ಣಗೊಳ್ಳುತ್ತದೆ"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ಬಳಕೆದಾರರನ್ನು ಬದಲಿಸಿ"</string>
<string name="accessibility_multi_user_switch_switcher_with_current" msgid="5759855008166759399">"ಬಳಕೆದಾರರನ್ನು ಬದಲಿಸಿ, ಪ್ರಸ್ತುತ ಬಳಕೆದಾರ <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_inactive" msgid="383168614528618402">"<xliff:g id="CURRENT_USER_NAME">%s</xliff:g> ಪ್ರಸ್ತುತ ಬಳಕೆದಾರ"</string>
@@ -1138,7 +1136,7 @@
<string name="audio_status" msgid="4237055636967709208">"ಆಲಿಸಲಾಗುತ್ತಿದೆ"</string>
<string name="game_status" msgid="1340694320630973259">"ಪ್ಲೇ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
<string name="empty_user_name" msgid="3389155775773578300">"ಸ್ನೇಹಿತರು"</string>
- <string name="empty_status" msgid="5938893404951307749">"ಈ ರಾತ್ರಿ ಚಾಟ್ ಮಾಡೋಣ!"</string>
+ <string name="empty_status" msgid="5938893404951307749">"ರಾತ್ರಿ ಚಾಟ್ ಮಾಡೋಣ!"</string>
<string name="status_before_loading" msgid="1500477307859631381">"ವಿಷಯ ಶೀಘ್ರದಲ್ಲೇ ಕಾಣಿಸಿಕೊಳ್ಳುತ್ತವೆ"</string>
<string name="missed_call" msgid="4228016077700161689">"ಮಿಸ್ಡ್ ಕಾಲ್"</string>
<string name="messages_count_overflow_indicator" msgid="7850934067082006043">"<xliff:g id="NUMBER">%d</xliff:g>+"</string>
@@ -1154,4 +1152,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"ದೃಢೀಕರಿಸಿ"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"ಸಾಧನವನ್ನು ಪ್ರವೇಶಿಸಿ"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"ತೆರೆಯುವುದಕ್ಕಾಗಿ ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಅನ್ನು ಬಳಸಿ"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 5f6bbcb..ea45bd9 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"카메라"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"전화"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"음성 지원"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"잠금 해제"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"기기 잠김"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"지문 대기 중"</string>
@@ -289,11 +291,9 @@
<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_casting_turned_off" msgid="1387906158563374962">"화면 전송이 중지되었습니다."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"직장 모드가 일시중지되어 있습니다."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"작업 모드가 사용 설정되었습니다."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"직장 모드가 일시중지되어 있습니다."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"작업 모드가 사용 설정되었습니다."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"데이터 절약 모드를 사용 중지했습니다."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"데이터 절약 모드를 사용 설정했습니다."</string>
@@ -412,8 +412,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"한도: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"<xliff:g id="DATA_LIMIT">%s</xliff:g> 경고"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"직장 프로필"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"일시중지됨"</string>
<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>
@@ -473,14 +472,10 @@
<string name="interruption_level_none_twoline" msgid="8579382742855486372">"모두\n차단"</string>
<string name="interruption_level_priority_twoline" msgid="8523482736582498083">"중요 알림만\n허용"</string>
<string name="interruption_level_alarms_twoline" msgid="2045067991335708767">"알람만\n"</string>
- <!-- no translation found for keyguard_indication_charging_time_wireless (577856646141738675) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time (6492711711891071502) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_fast (8390311020603859480) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_slowly (301936949731705417) -->
- <skip />
+ <string name="keyguard_indication_charging_time_wireless" msgid="577856646141738675">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 무선 충전 중 • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> 후 충전 완료"</string>
+ <string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 충전 중 • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> 후 충전 완료"</string>
+ <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 고속 충전 중 • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> 후 충전 완료"</string>
+ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 저속 충전 중 • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> 후 충전 완료"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"사용자 전환"</string>
<string name="accessibility_multi_user_switch_switcher_with_current" msgid="5759855008166759399">"사용자 전환, 현재 사용자 <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_inactive" msgid="383168614528618402">"현재 사용자: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -676,12 +671,10 @@
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"모두 표시"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"잠금 해제하여 결제"</string>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"설정되지 않음"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"잠금 해제하여 사용"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"카드를 가져오는 중에 문제가 발생했습니다. 나중에 다시 시도해 보세요."</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"잠금 화면 설정"</string>
<string name="status_bar_work" msgid="5238641949837091056">"직장 프로필"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"비행기 모드"</string>
<string name="add_tile" msgid="6239678623873086686">"타일 추가"</string>
@@ -871,8 +864,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"사용"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"사용 안함"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"사용할 수 없음"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"사용 안함"</string>
<string name="nav_bar" msgid="4642708685386136807">"탐색 메뉴"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"레이아웃"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"추가 왼쪽 버튼 유형"</string>
@@ -1144,7 +1136,7 @@
<string name="audio_status" msgid="4237055636967709208">"듣는 중"</string>
<string name="game_status" msgid="1340694320630973259">"플레이 중"</string>
<string name="empty_user_name" msgid="3389155775773578300">"친구"</string>
- <string name="empty_status" msgid="5938893404951307749">"오늘 밤에 채팅"</string>
+ <string name="empty_status" msgid="5938893404951307749">"오늘 밤에 채팅하자!"</string>
<string name="status_before_loading" msgid="1500477307859631381">"곧 콘텐츠가 표시됩니다."</string>
<string name="missed_call" msgid="4228016077700161689">"부재중 전화"</string>
<string name="messages_count_overflow_indicator" msgid="7850934067082006043">"<xliff:g id="NUMBER">%d</xliff:g>+"</string>
@@ -1160,4 +1152,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"인증"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"기기 입력"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"지문으로 열기"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 90b1600..d2db2c3 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Камера"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Телефон"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Үн жардамчысы"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"Кулпусун ачуу"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Түзмөк кулпуланды"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Манжаңызды сенсорго коюңуз"</string>
@@ -289,11 +291,9 @@
<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_casting_turned_off" msgid="1387906158563374962">"Тышкы экранга чыгаруу аракети токтотулду."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Иштөө режими тындырылган."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Иштөө режими күйүк."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Иштөө режими тындырылган."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Иштөө режими күйгүзүлдү."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Трафикти үнөмдөө режими өчүрүлдү."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Трафикти үнөмдөө режими күйгүзүлдү."</string>
@@ -412,8 +412,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"<xliff:g id="DATA_LIMIT">%s</xliff:g> чектөө"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"<xliff:g id="DATA_LIMIT">%s</xliff:g> эскертүү"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"Жумуш профили"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"Тындырылган"</string>
<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>
@@ -473,14 +472,10 @@
<string name="interruption_level_none_twoline" msgid="8579382742855486372">"Тым-\nтырс"</string>
<string name="interruption_level_priority_twoline" msgid="8523482736582498083">"Артыкчылыктуу\nгана"</string>
<string name="interruption_level_alarms_twoline" msgid="2045067991335708767">"Ойготкучтар\nгана"</string>
- <!-- no translation found for keyguard_indication_charging_time_wireless (577856646141738675) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time (6492711711891071502) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_fast (8390311020603859480) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_slowly (301936949731705417) -->
- <skip />
+ <string name="keyguard_indication_charging_time_wireless" msgid="577856646141738675">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Зымсыз кубатталууда • Толгонго чейин <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> калды"</string>
+ <string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Кубатталууда • Толгонго чейин <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> калды"</string>
+ <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Тез кубатталууда • Толгонго чейин <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> калды"</string>
+ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Жай кубатталууда • Толгонго чейин <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> калды"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Колдонуучуну которуу"</string>
<string name="accessibility_multi_user_switch_switcher_with_current" msgid="5759855008166759399">"Колдонуучуну күйгүзүү, учурдагы колдонуучу <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_inactive" msgid="383168614528618402">"Учурдагы колдонуучу <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -676,12 +671,10 @@
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Баарын көрсөтүү"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Төлөө үчүн кулпусун ачыңыз"</string>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Жөндөлгөн эмес"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Колдонуу үчүн кулпусун ачыңыз"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Кыйытмаларды алууда ката кетти. Бир аздан кийин кайталап көрүңүз."</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Кулпуланган экран жөндөөлөрү"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Жумуш профили"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Учак режими"</string>
<string name="add_tile" msgid="6239678623873086686">"Тайл кошуу"</string>
@@ -871,8 +864,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"Күйүк"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"Өчүк"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"Жеткиликсиз"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"Өчүрүлгөн"</string>
<string name="nav_bar" msgid="4642708685386136807">"Чабыттоо тилкеси"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"Калып"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"Сол жактагы кошумча баскычтын түрү"</string>
@@ -1124,12 +1116,12 @@
<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="recent_conversations" msgid="8531874684782574622">"Акыркы жазышуулар"</string>
+ <string name="priority_conversations" msgid="3967482288896653039">"Маанилүү сүйлөшүүлөр"</string>
+ <string name="recent_conversations" msgid="8531874684782574622">"Акыркы сүйлөшүүлөр"</string>
<string name="okay" msgid="6490552955618608554">"Макул"</string>
<string name="timestamp" msgid="6577851592534538533">"<xliff:g id="DURATION">%1$s</xliff:g> мурда"</string>
<string name="less_than_timestamp" msgid="6598972791137724517">"<xliff:g id="DURATION">%1$s</xliff:g> жетпеген убакыт мурда"</string>
- <string name="over_timestamp" msgid="4765793502859358634">"<xliff:g id="DURATION">%1$s</xliff:g> ашуун мурда"</string>
+ <string name="over_timestamp" msgid="4765793502859358634">"<xliff:g id="DURATION">%1$s</xliff:g> мурун"</string>
<string name="birthday_status" msgid="2596961629465396761">"Туулган күн"</string>
<string name="birthday_status_content_description" msgid="682836371128282925">"<xliff:g id="NAME">%1$s</xliff:g> бүгүн туулган күнүн белгилеп жатат"</string>
<string name="upcoming_birthday_status" msgid="2005452239256870351">"Алдыдагы туулган күн"</string>
@@ -1148,7 +1140,7 @@
<string name="status_before_loading" msgid="1500477307859631381">"Мазмун бир аздан кийин көрүнөт"</string>
<string name="missed_call" msgid="4228016077700161689">"Жооп берилбеген чалуу"</string>
<string name="messages_count_overflow_indicator" msgid="7850934067082006043">"<xliff:g id="NUMBER">%d</xliff:g>+"</string>
- <string name="people_tile_description" msgid="8154966188085545556">"Акыркы билдирүүлөрдү, жооп берилбеген чалууларды жана статус жаңыртууларын көрүү"</string>
+ <string name="people_tile_description" msgid="8154966188085545556">"Акыркы билдирүүлөрдү, жооп берилбеген чалууларды жана статустардын жаңырганын көрөсүз"</string>
<string name="people_tile_title" msgid="6589377493334871272">"Сүйлөшүү"</string>
<string name="new_notification_text_content_description" msgid="5574393603145263727">"<xliff:g id="NAME">%1$s</xliff:g> билдирүү жөнөттү"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> сүрөт жөнөттү"</string>
@@ -1160,4 +1152,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"аныктыгын текшерүү"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"түзмөккө кирүү"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Манжаңыздын изи менен ачыңыз"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 5d70e13..c162c54 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"ກ້ອງ"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"ໂທລະສັບ"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"ຊ່ວຍເຫຼືອທາງສຽງ"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"ປົດລັອກ"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"ອຸປະກອນຖືກລັອກໄວ້"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"ກຳລັງລໍຖ້າລາຍນິ້ວມື"</string>
@@ -289,11 +291,9 @@
<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_casting_turned_off" msgid="1387906158563374962">"ຢຸດການສົ່ງພາບໜ້າຈໍແລ້ວ."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"ຢຸດໂໝດວຽກຊົ່ວຄາວແລ້ວ."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"ໂໝດການເຮັດວຽກເປີດຢູ່."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"ຢຸດໂໝດວຽກໄວ້ຊົ່ວຄາວແລ້ວ."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"ໂໝດການເຮັດວຽກເປີດຢູ່."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"ປິດຕົວປະຢັດອິນເຕີເນັດແລ້ວ."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"ເປີດຕົວປະຢັດອິນເຕີເນັດແລ້ວ."</string>
@@ -412,8 +412,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"ຈຳກັດ <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"ຄຳເຕືອນ <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"ໂປຣໄຟລ໌ບ່ອນເຮັດວຽກ"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"ຢຸດຊົ່ວຄາວແລ້ວ"</string>
<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>
@@ -672,12 +671,10 @@
<string name="wallet_title" msgid="5369767670735827105">"ກະເປົາ"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"ສະແດງທັງໝົດ"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"ປົດລັອກເພື່ອຈ່າຍ"</string>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"ບໍ່ໄດ້ຕັ້ງຄ່າ"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ປົດລັອກເພື່ອໃຊ້"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"ເກີດບັນຫາໃນການໂຫຼດບັດຂອງທ່ານ, ກະລຸນາລອງໃໝ່ໃນພາຍຫຼັງ"</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"ການຕັ້ງຄ່າໜ້າຈໍລັອກ"</string>
<string name="status_bar_work" msgid="5238641949837091056">"ໂປຣໄຟລ໌ບ່ອນເຮັດວຽກ"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"ໂໝດເຮືອບິນ"</string>
<string name="add_tile" msgid="6239678623873086686">"ເພີ່ມລາຍຕາກະໂລ່"</string>
@@ -867,8 +864,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"ເປີດ"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"ປິດ"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"ບໍ່ສາມາດໃຊ້ໄດ້"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"ປິດການນຳໃຊ້ແລ້ວ"</string>
<string name="nav_bar" msgid="4642708685386136807">"ແຖບນຳທາງ"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"ຮູບແບບ"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"ປະເພດປຸ່ມຊ້າຍພິເສດ"</string>
@@ -1156,4 +1152,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"ພິສູດຢືນຢັນ"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"ເຂົ້າອຸປະກອນ"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"ໃຊ້ລາຍນິ້ວມືເພື່ອເປີດ"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index fdb8c10..3a9ccf0 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Fotoaparatas"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Telefonas"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Voice Assist"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"Atrakinti"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Įrenginys užrakintas"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Laukiama piršto antspaudo"</string>
@@ -289,11 +291,9 @@
<string name="accessibility_quick_settings_hotspot_changed_off" msgid="7002061268910095176">"Mobiliojo ryšio viešosios interneto prieigos taškas išjungtas."</string>
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2576895346762408840">"Mobiliojo ryšio viešosios interneto prieigos taškas įjungtas."</string>
<string name="accessibility_casting_turned_off" msgid="1387906158563374962">"Ekrano perdavimas sustabdytas."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Darbo režimas pristabdytas."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Darbo režimas įjungtas."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Darbo režimas pristabdytas."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Darbo režimas įjungtas."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Duomenų taupymo priemonė išjungta."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Duomenų taupymo priemonė įjungta."</string>
@@ -416,8 +416,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"Limitas: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"<xliff:g id="DATA_LIMIT">%s</xliff:g> įspėjimas"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"Darbo profilis"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"Pristabdyta"</string>
<string name="quick_settings_night_display_label" msgid="8180030659141778180">"Nakties šviesa"</string>
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Per saulėlydį"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"Iki saulėtekio"</string>
@@ -678,12 +677,10 @@
<string name="wallet_title" msgid="5369767670735827105">"Piniginė"</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>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Nenustatyta"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Atrakinti, kad būtų galima naudoti"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Gaunant korteles kilo problema, bandykite dar kartą vėliau"</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Užrakinimo ekrano nustatymai"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Darbo profilis"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Lėktuvo režimas"</string>
<string name="add_tile" msgid="6239678623873086686">"Pridėti išklotinės elementą"</string>
@@ -877,8 +874,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"Įjungta"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"Išjungta"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"Nepasiekiama"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"Išjungta"</string>
<string name="nav_bar" msgid="4642708685386136807">"Naršymo juosta"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"Išdėstymas"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"Papildomo mygtuko kairėje tipas"</string>
@@ -1168,4 +1164,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"nustatytumėte tapatybę"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"pasiektumėte įrenginį"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Naudokite kontrolinį kodą, kad atidarytumėte"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 307f0b6..c583cba 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Kamera"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Tālruņa numurs"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Balss palīgs"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"Atbloķēt"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Ierīce ir bloķēta"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Tiek gaidīts pirksta nospiedums."</string>
@@ -289,11 +291,9 @@
<string name="accessibility_quick_settings_hotspot_changed_off" msgid="7002061268910095176">"Mobilais tīklājs ir izslēgts."</string>
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2576895346762408840">"Mobilais tīklājs ir ieslēgts."</string>
<string name="accessibility_casting_turned_off" msgid="1387906158563374962">"Ekrāna apraidīšana ir apturēta."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Darba režīms pārtraukts."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Darba režīms ir ieslēgts."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Darba režīms ir pārtraukts."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Darba režīms ir ieslēgts."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Datu lietojuma samazinātājs ir izslēgts."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Datu lietojuma samazinātājs ir ieslēgts."</string>
@@ -414,8 +414,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"Ierobežojums: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"<xliff:g id="DATA_LIMIT">%s</xliff:g> brīdinājums"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"Darba profils"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"Pārtraukts"</string>
<string name="quick_settings_night_display_label" msgid="8180030659141778180">"Nakts režīms"</string>
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Saulrietā"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"Līdz saullēktam"</string>
@@ -475,14 +474,10 @@
<string name="interruption_level_none_twoline" msgid="8579382742855486372">"Pilnīgs\nklusums"</string>
<string name="interruption_level_priority_twoline" msgid="8523482736582498083">"Tikai\nprioritārie"</string>
<string name="interruption_level_alarms_twoline" msgid="2045067991335708767">"Tikai\nsignāli"</string>
- <!-- no translation found for keyguard_indication_charging_time_wireless (577856646141738675) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time (6492711711891071502) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_fast (8390311020603859480) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_slowly (301936949731705417) -->
- <skip />
+ <string name="keyguard_indication_charging_time_wireless" msgid="577856646141738675">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Bezvadu uzlāde • Laiks līdz pilnai uzlādei: <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Notiek uzlāde • Laiks līdz pilnai uzlādei: <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ātrā uzlāde • Laiks līdz pilnai uzlādei: <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Lēnā uzlāde • Laiks līdz pilnai uzlādei: <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Mainīt lietotāju"</string>
<string name="accessibility_multi_user_switch_switcher_with_current" msgid="5759855008166759399">"Pārslēgt lietotāju; pašreizējais lietotājs: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_inactive" msgid="383168614528618402">"Pašreizējais lietotājs: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -679,12 +674,10 @@
<string name="wallet_title" msgid="5369767670735827105">"Maks"</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>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Nav iestatīts"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Lai izmantotu, atbloķējiet ekrānu"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Ienesot jūsu kartes, radās problēma. Lūdzu, vēlāk mēģiniet vēlreiz."</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Bloķēšanas ekrāna iestatījumi"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Darba profils"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Lidojuma režīms"</string>
<string name="add_tile" msgid="6239678623873086686">"Pievienot elementu"</string>
@@ -876,8 +869,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"Ieslēgts"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"Izslēgts"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"Nav pieejams"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"Atspējots"</string>
<string name="nav_bar" msgid="4642708685386136807">"Navigācijas josla"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"Izkārtojums"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"Kreisās puses papildu pogas veids"</string>
@@ -1166,4 +1158,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"veiktu autentificēšanu"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"izmantotu ierīci"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Atvēršanai izmantojiet pirksta nospiedumu"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index fdb76bb..d306e1f 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Камера"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Телефон"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Гласовна помош"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"Отклучување"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Уредот е заклучен"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Се чека отпечаток"</string>
@@ -289,11 +291,9 @@
<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_casting_turned_off" msgid="1387906158563374962">"Емитувањето на екранот запре."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Режимот на работа е паузиран."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Режимот на работа е вклучен."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Режимот на работа е паузиран."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Режимот на работа е вклучен."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Штедачот на интернет е исклучен."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Штедачот на интернет е вклучен."</string>
@@ -412,8 +412,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"Лимит: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"Предупредување: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"Работен профил"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"Паузиран"</string>
<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>
@@ -672,12 +671,10 @@
<string name="wallet_title" msgid="5369767670735827105">"Паричник"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Прикажи ги сите"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Отклучете за да платите"</string>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Не е поставено"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Отклучете за да користите"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Имаше проблем при преземањето на картичките. Обидете се повторно подоцна"</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Поставки за заклучен екран"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Работен профил"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Авионски режим"</string>
<string name="add_tile" msgid="6239678623873086686">"Додај плочка"</string>
@@ -867,8 +864,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"Вклучено"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"Исклучено"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"Недостапно"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"Оневозможено"</string>
<string name="nav_bar" msgid="4642708685386136807">"Лента за навигација"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"Распоред"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"Тип дополнително лево копче"</string>
@@ -1156,4 +1152,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"автентицирате"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"внесете уред"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Користете отпечаток за да се отвори"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index e793e19b..750d834 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"ക്യാമറ"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"ഫോണ്"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"വോയ്സ് സഹായം"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"അണ്ലോക്ക് ചെയ്യുക"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"ഉപകരണം ലോക്ക് ചെയ്തു"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"ഫിംഗർപ്രിന്റിനായി കാത്തിരിക്കുന്നു"</string>
@@ -289,10 +291,9 @@
<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_casting_turned_off" msgid="1387906158563374962">"സ്ക്രീൻ കാസ്റ്റുചെയ്യൽ നിർത്തി."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"പ്രവർത്തന മോഡ് താൽക്കാലികമായി നിർത്തി."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"പ്രവർത്തന മോഡ് ഓണാണ്."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
+ <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (6422896967647049692) -->
<skip />
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"പ്രവർത്തന മോഡ് ഓണാക്കി."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"ഡാറ്റ സേവർ ഓഫാക്കി."</string>
@@ -412,8 +413,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"<xliff:g id="DATA_LIMIT">%s</xliff:g> പരിധി"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"<xliff:g id="DATA_LIMIT">%s</xliff:g> മുന്നറിയിപ്പ്"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"ഔദ്യോഗിക പ്രൊഫൈൽ"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"താൽക്കാലികമായി നിർത്തി"</string>
<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>
@@ -473,14 +473,10 @@
<string name="interruption_level_none_twoline" msgid="8579382742855486372">"പൂർണ്ണ\nനിശബ്ദത"</string>
<string name="interruption_level_priority_twoline" msgid="8523482736582498083">"മുൻഗണന\nമാത്രം"</string>
<string name="interruption_level_alarms_twoline" msgid="2045067991335708767">"അലാറങ്ങൾ\nമാത്രം"</string>
- <!-- no translation found for keyguard_indication_charging_time_wireless (577856646141738675) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time (6492711711891071502) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_fast (8390311020603859480) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_slowly (301936949731705417) -->
- <skip />
+ <string name="keyguard_indication_charging_time_wireless" msgid="577856646141738675">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • വയർലെസ്സ് ആയി ചാർജ് ചെയ്യുന്നു • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>-ൽ പൂർത്തിയാകും"</string>
+ <string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ചാർജ് ചെയ്യുന്നു • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>-ൽ പൂർത്തിയാകും"</string>
+ <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • വേഗത്തിൽ ചാർജ് ചെയ്യുന്നു • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>-ൽ പൂർത്തിയാകും"</string>
+ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • പതുക്കെ ചാർജ് ചെയ്യുന്നു • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>-ൽ പൂർത്തിയാകും"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ഉപയോക്താവ് മാറുക"</string>
<string name="accessibility_multi_user_switch_switcher_with_current" msgid="5759855008166759399">"ഉപയോക്താവിനെ മാറ്റുക, <xliff:g id="CURRENT_USER_NAME">%s</xliff:g> എന്നയാളാണ് നിലവിലുള്ള ഉപയോക്താവ്"</string>
<string name="accessibility_multi_user_switch_inactive" msgid="383168614528618402">"നിലവിലെ ഉപയോക്താവ് <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -676,12 +672,10 @@
<string name="wallet_title" msgid="5369767670735827105">"വാലറ്റ്"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"എല്ലാം കാണിക്കുക"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"പണമടയ്ക്കാൻ അൺലോക്ക് ചെയ്യുക"</string>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"സജ്ജീകരിച്ചിട്ടില്ല"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ഉപയോഗിക്കാൻ അൺലോക്ക് ചെയ്യുക"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"നിങ്ങളുടെ കാർഡുകൾ ലഭ്യമാക്കുന്നതിൽ ഒരു പ്രശ്നമുണ്ടായി, പിന്നീട് വീണ്ടും ശ്രമിക്കുക"</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"ലോക്ക് സ്ക്രീൻ ക്രമീകരണം"</string>
<string name="status_bar_work" msgid="5238641949837091056">"ഔദ്യോഗിക പ്രൊഫൈൽ"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"ഫ്ലൈറ്റ് മോഡ്"</string>
<string name="add_tile" msgid="6239678623873086686">"ടൈൽ ചേർക്കുക"</string>
@@ -871,8 +865,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"ഓൺ"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"ഓഫ്"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"ലഭ്യമല്ല"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"പ്രവർത്തനരഹിതമാക്കി"</string>
<string name="nav_bar" msgid="4642708685386136807">"നാവിഗേഷൻ ബാർ"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"ലേഔട്ട്"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"അധിക ഇടത് ബട്ടൺ തരം"</string>
@@ -1144,11 +1137,11 @@
<string name="audio_status" msgid="4237055636967709208">"കേൾക്കുന്നു"</string>
<string name="game_status" msgid="1340694320630973259">"കളിക്കുന്നു"</string>
<string name="empty_user_name" msgid="3389155775773578300">"സുഹൃത്തുക്കൾ"</string>
- <string name="empty_status" msgid="5938893404951307749">"ഇന്നുരാത്രി ചാറ്റുചെയ്യാം!"</string>
+ <string name="empty_status" msgid="5938893404951307749">"ഇന്നുരാത്രി ചാറ്റ് ചെയ്യാം!"</string>
<string name="status_before_loading" msgid="1500477307859631381">"ഉള്ളടക്കം ഉടൻ ദൃശ്യമാകും"</string>
<string name="missed_call" msgid="4228016077700161689">"മിസ്ഡ് കോൾ"</string>
<string name="messages_count_overflow_indicator" msgid="7850934067082006043">"<xliff:g id="NUMBER">%d</xliff:g>+"</string>
- <string name="people_tile_description" msgid="8154966188085545556">"അടുത്തിടെയുള്ള സന്ദേശങ്ങൾ, മിസ്ഡ് കോളുകൾ, സ്റ്റാറ്റസ് അപ്ഡേറ്റുകൾ എന്നിവ കാണുക"</string>
+ <string name="people_tile_description" msgid="8154966188085545556">"അടുത്തിടെയുള്ള സന്ദേശങ്ങൾ, മിസ്ഡ് കോൾ, സ്റ്റാറ്റസ് അപ്ഡേറ്റുകൾ എന്നിവ കാണൂ"</string>
<string name="people_tile_title" msgid="6589377493334871272">"സംഭാഷണം"</string>
<string name="new_notification_text_content_description" msgid="5574393603145263727">"<xliff:g id="NAME">%1$s</xliff:g>, ഒരു സന്ദേശം അയച്ചു"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g>, ഒരു ചിത്രം അയച്ചു"</string>
@@ -1160,4 +1153,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"പരിശോധിച്ചുറപ്പിക്കുക"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"ഉപകരണം നൽകുക"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"തുറക്കുന്നതിന് നിങ്ങളുടെ ഫിംഗർപ്രിന്റ് ഉപയോഗിക്കുക"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 8d3dffd..583b083 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Камер"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Утас"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Дуут туслах"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"Тайлах"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Төхөөрөмжийг түгжсэн"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Хурууны хээг хүлээж байна"</string>
@@ -289,11 +291,9 @@
<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_casting_turned_off" msgid="1387906158563374962">"Дэлгэц дамжуулалт зогссон."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Ажлыг горимыг түр зогсоосон."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Ажлын горимыг асаасан."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Ажлыг горимыг түр зогсоосон."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Ажлын горимыг асаасан."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Дата хэмнэгчийг унтраасан."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Дата хэмнэгчийг асаасан."</string>
@@ -412,8 +412,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"<xliff:g id="DATA_LIMIT">%s</xliff:g> хязгаар"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"<xliff:g id="DATA_LIMIT">%s</xliff:g> анхааруулга"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"Ажлын профайл"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"Түр зогсоосон"</string>
<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>
@@ -672,12 +671,10 @@
<string name="wallet_title" msgid="5369767670735827105">"Түрийвч"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Бүгдийг харуулах"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Төлөхийн тулд түгжээг тайлна уу"</string>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Тохируулаагүй"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Ашиглахын тулд түгжээг тайлах"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Таны картыг авахад асуудал гарлаа. Дараа дахин оролдоно уу"</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Түгжигдсэн дэлгэцийн тохиргоо"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Ажлын профайл"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Нислэгийн горим"</string>
<string name="add_tile" msgid="6239678623873086686">"Вебсайтын цонх нэмэх"</string>
@@ -867,8 +864,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"Идэвхтэй"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"Идэвхгүй"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"Боломжгүй"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"Идэвхгүй болгосон"</string>
<string name="nav_bar" msgid="4642708685386136807">"Навигацын самбар"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"Бүдүүвч"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"Нэмэлт зүүн товчлуураар шивэх"</string>
@@ -1156,4 +1152,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"баталгаажуулах"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"төхөөрөмж оруулах"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Нээхийн тулд хурууны хээг ашиглана уу"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index f26bf31..8fe5af0 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"कॅमेरा"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"फोन"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"व्हॉइस सहाय्य"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"अनलॉक करा"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"डिव्हाइस लॉक केले"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"फिंगरप्रिंटची प्रतीक्षा करत आहे"</string>
@@ -289,10 +291,9 @@
<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_casting_turned_off" msgid="1387906158563374962">"स्क्रीन कास्ट करणे थांबले."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"कार्य मोड थांबवला."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"कार्य मोड सुरू."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
+ <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (6422896967647049692) -->
<skip />
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"कार्य मोड सुरू केला."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"डेटा सर्व्हर बंद केला."</string>
@@ -412,8 +413,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"<xliff:g id="DATA_LIMIT">%s</xliff:g> मर्यादा"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"<xliff:g id="DATA_LIMIT">%s</xliff:g> चेतावणी"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"कार्य प्रोफाइल"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"थाबंवला"</string>
<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>
@@ -473,14 +473,10 @@
<string name="interruption_level_none_twoline" msgid="8579382742855486372">"संपूर्ण\nशांतता"</string>
<string name="interruption_level_priority_twoline" msgid="8523482736582498083">"केवळ\nप्राधान्य"</string>
<string name="interruption_level_alarms_twoline" msgid="2045067991335708767">"केवळ\nअलार्म"</string>
- <!-- no translation found for keyguard_indication_charging_time_wireless (577856646141738675) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time (6492711711891071502) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_fast (8390311020603859480) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_slowly (301936949731705417) -->
- <skip />
+ <string name="keyguard_indication_charging_time_wireless" msgid="577856646141738675">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • वायरलेस पद्धतीने चार्ज होत आहे • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> मध्ये पूर्ण होईल"</string>
+ <string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • चार्ज होत आहे • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> मध्ये पूर्ण होईल"</string>
+ <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • वेगाने चार्ज होत आहे • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> मध्ये पूर्ण होईल"</string>
+ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • हळू चार्ज होत आहे • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> मध्ये पूर्ण होईल"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"वापरकर्ता स्विच करा"</string>
<string name="accessibility_multi_user_switch_switcher_with_current" msgid="5759855008166759399">"वापरकर्ता स्विच करा, वर्तमान वापरकर्ता <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_inactive" msgid="383168614528618402">"वर्तमान वापरकर्ता <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -676,12 +672,10 @@
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"सर्व दाखवा"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"पैसे देण्यासाठी अनलॉक करा"</string>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"सेट केलेले नाही"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"वापरण्यासाठी अनलॉक करा"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"तुमची कार्ड मिळवताना समस्या आली, कृपया नंतर पुन्हा प्रयत्न करा"</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"लॉक स्क्रीन सेटिंग्ज"</string>
<string name="status_bar_work" msgid="5238641949837091056">"कार्य प्रोफाईल"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"विमान मोड"</string>
<string name="add_tile" msgid="6239678623873086686">"टाइल जोडा"</string>
@@ -871,8 +865,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"सुरू"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"बंद"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"उपलब्ध नाही"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"बंद केली"</string>
<string name="nav_bar" msgid="4642708685386136807">"नॅव्हिगेशन बार"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"लेआउट"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"अतिरिक्त डाव्या बटणाचा प्रकार"</string>
@@ -1144,7 +1137,7 @@
<string name="audio_status" msgid="4237055636967709208">"ऐकत आहे"</string>
<string name="game_status" msgid="1340694320630973259">"प्ले करत आहे"</string>
<string name="empty_user_name" msgid="3389155775773578300">"मित्रमैत्रिणी"</string>
- <string name="empty_status" msgid="5938893404951307749">"चला, आज रात्री चॅट करूया!"</string>
+ <string name="empty_status" msgid="5938893404951307749">"आज रात्री चॅट करू या"</string>
<string name="status_before_loading" msgid="1500477307859631381">"आशय लवकरच दाखवला जाईल"</string>
<string name="missed_call" msgid="4228016077700161689">"मिस्ड कॉल"</string>
<string name="messages_count_overflow_indicator" msgid="7850934067082006043">"<xliff:g id="NUMBER">%d</xliff:g>+"</string>
@@ -1160,4 +1153,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"ऑथेंटिकेट करा"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"डिव्हाइस एंटर करा"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"उघडण्यासाठी फिंगरप्रिंट वापरा"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 267b74a..791863a 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Kamera"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Telefon"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Bantuan Suara"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"Buka kunci"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Peranti dikunci"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Menunggu cap jari"</string>
@@ -291,7 +293,7 @@
<string name="accessibility_casting_turned_off" msgid="1387906158563374962">"Penghantaran skrin dihentikan."</string>
<string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Mod kerja dijeda."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Mod kerja hidup."</string>
- <string name="accessibility_quick_settings_work_mode_changed_off" msgid="2653550342355027441">"Mod kerja dijeda."</string>
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Mod kerja dijeda."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Mod kerja dihidupkan."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Penjimat Data dimatikan."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Penjimat Data dihidupkan."</string>
@@ -470,14 +472,10 @@
<string name="interruption_level_none_twoline" msgid="8579382742855486372">"Senyap\nsepenuhnya"</string>
<string name="interruption_level_priority_twoline" msgid="8523482736582498083">"Keutamaan\nsahaja"</string>
<string name="interruption_level_alarms_twoline" msgid="2045067991335708767">"Penggera\nsahaja"</string>
- <!-- no translation found for keyguard_indication_charging_time_wireless (577856646141738675) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time (6492711711891071502) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_fast (8390311020603859480) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_slowly (301936949731705417) -->
- <skip />
+ <string name="keyguard_indication_charging_time_wireless" msgid="577856646141738675">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengecas secara wayarles • Penuh dalam masa <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengecas • Penuh dalam masa <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengecas dengan cepat • Penuh dalam masa <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengecas dengan perlahan • Penuh dalam masa <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Tukar pengguna"</string>
<string name="accessibility_multi_user_switch_switcher_with_current" msgid="5759855008166759399">"Tukar pengguna, pengguna semasa <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_inactive" msgid="383168614528618402">"Pengguna semasa <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -1154,4 +1152,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"sahkan"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"akses peranti"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Gunakan cap jari untuk membuka"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 1756d28..769c962 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"ကင်မရာ"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"ဖုန်း"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"အသံ အကူအညီ"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"သော့ဖွင့်ရန်"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"စက်ပစ္စည်းကို လော့ခ်ချထားသည်"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"လက်ဗွေကို စောင့်နေသည်"</string>
@@ -289,11 +291,9 @@
<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_casting_turned_off" msgid="1387906158563374962">"မျက်နှာပြင် ကာစ်တင် လုပ်မှု ရပ်လိုက်ပြီ။"</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"အလုပ်မုဒ် ခဏရပ်ထားသည်။"</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"အလုပ် မုဒ်ကို ဖွင့်ထားပါသည်။"</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"အလုပ်မုဒ် ခဏရပ်ထားသည်။"</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"အလုပ် မုဒ်ကို ဖွင့်ထားပါသည်။"</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"ဒေတာချွေတာမှု ပိတ်ထားသည်။"</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"ဒေတာချွေတာမှု ဖွင့်ထားသည်။"</string>
@@ -412,8 +412,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"<xliff:g id="DATA_LIMIT">%s</xliff:g> ကန့်သတ်ချက်"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"<xliff:g id="DATA_LIMIT">%s</xliff:g> သတိပေးချက်"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"အလုပ်ပရိုဖိုင်"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"ခဏရပ်ထားသည်"</string>
<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>
@@ -473,14 +472,10 @@
<string name="interruption_level_none_twoline" msgid="8579382742855486372">"လုံးဝ\nတိတ်ဆိတ်ခြင်း"</string>
<string name="interruption_level_priority_twoline" msgid="8523482736582498083">"ဦးစားပေးမှု\nသာ"</string>
<string name="interruption_level_alarms_twoline" msgid="2045067991335708767">"နှိုးစက်များ\nသာ"</string>
- <!-- no translation found for keyguard_indication_charging_time_wireless (577856646141738675) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time (6492711711891071502) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_fast (8390311020603859480) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_slowly (301936949731705417) -->
- <skip />
+ <string name="keyguard_indication_charging_time_wireless" msgid="577856646141738675">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ကြိုးမဲ့အားသွင်းနေသည် • အားပြည့်ရန် <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> လိုသည်"</string>
+ <string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • အားသွင်းနေသည် • အားပြည့်ရန် <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> လိုသည်"</string>
+ <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • အမြန်အားသွင်းနေသည် • အားပြည့်ရန် <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> လိုသည်"</string>
+ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • နှေးကွေးစွာ အားသွင်းနေသည် • အားပြည့်ရန် <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> လိုသည်"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"အသုံးပြုသူကို ပြောင်းလဲရန်"</string>
<string name="accessibility_multi_user_switch_switcher_with_current" msgid="5759855008166759399">"အသုံးပြုသူကို ပြောင်းရန်၊ လက်ရှိ အသုံးပြုသူ <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_inactive" msgid="383168614528618402">"လတ်တလော သုံးစွဲသူ <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -676,12 +671,10 @@
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"အားလုံးပြရန်"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"ငွေပေးချေရန် လော့ခ်ဖွင့်ပါ"</string>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"စနစ် ထည့်သွင်းမထားပါ"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"သုံးရန် လော့ခ်ဖွင့်ပါ"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"သင်၏ကတ်များ ရယူရာတွင် ပြဿနာရှိနေသည်၊ နောက်မှ ထပ်စမ်းကြည့်ပါ"</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"လော့ခ်မျက်နှာပြင် ဆက်တင်များ"</string>
<string name="status_bar_work" msgid="5238641949837091056">"အလုပ် ပရိုဖိုင်"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"လေယာဉ်ပျံမုဒ်"</string>
<string name="add_tile" msgid="6239678623873086686">"လေးထောင့်ကွက် ထည့်ရန်"</string>
@@ -871,8 +864,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"ဖွင့်"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"ပိတ်"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"မရနိုင်ပါ"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"ပိတ်ထားသည်"</string>
<string name="nav_bar" msgid="4642708685386136807">"ရွှေ့လျားရန်ဘားတန်း"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"အပြင်အဆင်"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"လက်ဝဲခလုတ် အမျိုးအစားအပို"</string>
@@ -1123,7 +1115,7 @@
<string name="basic_status" msgid="2315371112182658176">"စကားဝိုင်းကို ဖွင့်ရန်"</string>
<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="no_conversations_text" msgid="7362374212649891057">"မက်ဆေ့ဂျ်အချို့ရလျှင် ဤနေရာသို့ ပြန်လာကြည့်ပါ"</string>
<string name="priority_conversations" msgid="3967482288896653039">"ဦးစားပေး စကားဝိုင်းများ"</string>
<string name="recent_conversations" msgid="8531874684782574622">"မကြာသေးမီက စကားဝိုင်းများ"</string>
<string name="okay" msgid="6490552955618608554">"OK"</string>
@@ -1160,4 +1152,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"အထောက်အထားစိစစ်ရန်"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"စက်ပစ္စည်းသို့ ဝင်ရန်"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"ဖွင့်ရန် လက်ဗွေကို သုံးပါ"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index cf82ea4..c0aefb0 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -136,6 +136,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Kamera"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Telefonnummer"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Talehjelp"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"Lås opp"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Enheten er låst"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Venger på fingeravtrykk"</string>
@@ -289,11 +290,9 @@
<string name="accessibility_quick_settings_hotspot_changed_off" msgid="7002061268910095176">"Mobil Wi-Fi-sone er slått av."</string>
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2576895346762408840">"Mobil Wi-Fi-sone er slått på."</string>
<string name="accessibility_casting_turned_off" msgid="1387906158563374962">"Skjermcastingen er stoppet."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Arbeidsmodus er satt på pause."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Arbeidsmodusen er på."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Arbeidsmodus er satt på pause."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Arbeidsmodusen er slått på."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Datasparing er slått av."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Datasparing er slått på."</string>
@@ -412,8 +411,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"Grense på <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"Advarsel for <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"Jobbprofil"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"Satt på pause"</string>
<string name="quick_settings_night_display_label" msgid="8180030659141778180">"Nattlys"</string>
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"På ved solnedgang"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"Til soloppgang"</string>
@@ -672,12 +670,10 @@
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</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>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Ikke konfigurert"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Lås opp for å bruke"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Det oppsto et problem med henting av kortene. Prøv igjen senere"</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Innstillinger for låseskjermen"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Work-profil"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Flymodus"</string>
<string name="add_tile" msgid="6239678623873086686">"Legg til felt"</string>
@@ -867,8 +863,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"På"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"Av"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"Utilgjengelig"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"Slått av"</string>
<string name="nav_bar" msgid="4642708685386136807">"Navigasjonsrad"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"Oppsett"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"Ekstra venstre-knapptype"</string>
@@ -1156,4 +1151,6 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"autentiser"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"åpne enheten"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Bruk fingeravtrykk for å åpne"</string>
+ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autentisering kreves. Trykk på fingeravtrykkssensoren for å autentisere."</string>
+ <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Pågående telefonsamtale"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index 7c1e919..de375d3 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"क्यामेरा"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"फोन"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"आवाज सहायता"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"खोल्नुहोस्"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"यन्त्र लक गरिएको छ"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"फिंगरप्रिन्ट कुर्दै"</string>
@@ -289,10 +291,9 @@
<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_casting_turned_off" msgid="1387906158563374962">"स्क्रिन कास्टिङ रोकियो।"</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"कामसम्बन्धी मोड पज गरियो।"</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"कार्य मोड अन।"</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
+ <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (6422896967647049692) -->
<skip />
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"कार्य मोड सक्रिय भयो।"</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"डेटा सेभरलाई निष्क्रिय पारियो।"</string>
@@ -412,8 +413,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"<xliff:g id="DATA_LIMIT">%s</xliff:g> सीमा"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"<xliff:g id="DATA_LIMIT">%s</xliff:g> चेतावनी दिँदै"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"कार्य प्रोफाइल"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"पज गरियो"</string>
<string name="quick_settings_night_display_label" msgid="8180030659141778180">"Night Light"</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>
@@ -473,14 +473,10 @@
<string name="interruption_level_none_twoline" msgid="8579382742855486372">"पूरै\nशान्त"</string>
<string name="interruption_level_priority_twoline" msgid="8523482736582498083">"प्राथमिकता \nमात्र"</string>
<string name="interruption_level_alarms_twoline" msgid="2045067991335708767">"अलार्महरू \nमात्र"</string>
- <!-- no translation found for keyguard_indication_charging_time_wireless (577856646141738675) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time (6492711711891071502) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_fast (8390311020603859480) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_slowly (301936949731705417) -->
- <skip />
+ <string name="keyguard_indication_charging_time_wireless" msgid="577856646141738675">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • तारविनै चार्ज हुँदै छ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> मा पूरै चार्ज हुन्छ"</string>
+ <string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • चार्ज हुँदै छ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> मा पूरै चार्ज हुन्छ"</string>
+ <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • छिटो चार्ज हुँदै छ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> मा पूरै चार्ज हुन्छ"</string>
+ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • बिस्तारै चार्ज हुँदै छ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> मा पूरै चार्ज हुन्छ"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"प्रयोगकर्ता फेर्नुहोस्"</string>
<string name="accessibility_multi_user_switch_switcher_with_current" msgid="5759855008166759399">"प्रयोगकर्ता, हालको प्रयोगकर्ता <xliff:g id="CURRENT_USER_NAME">%s</xliff:g> मा स्विच गर्नुहोस्"</string>
<string name="accessibility_multi_user_switch_inactive" msgid="383168614528618402">"हालको प्रयोगकर्ता <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -676,12 +672,10 @@
<string name="wallet_title" msgid="5369767670735827105">"वालेट"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"सबै देखाइयोस्"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"भुक्तानी गर्न अनलक गर्नुहोस्"</string>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"सेटअप गरिएको छैन"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"यो वालेट प्रयोग गर्न डिभाइस अनलक गर्नुहोस्"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"तपाईंका कार्डहरू प्राप्त गर्ने क्रममा समस्या भयो, कृपया पछि फेरि प्रयास गर्नुहोस्"</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"लक स्क्रिनसम्बन्धी सेटिङ"</string>
<string name="status_bar_work" msgid="5238641949837091056">"कार्य प्रोफाइल"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"हवाइजहाज मोड"</string>
<string name="add_tile" msgid="6239678623873086686">"टाइल थप्नुहोस्"</string>
@@ -871,8 +865,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"अन छ"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"अफ छ"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"उपलब्ध छैन"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"अफ गरियो"</string>
<string name="nav_bar" msgid="4642708685386136807">"नेभिगेशन पट्टी"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"लेआउट"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"अतिरिक्त बायाँतिरको बटनको प्रकार"</string>
@@ -1160,4 +1153,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"प्रमाणित गर्नुहोस्"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"डिभाइस हाल्नुहोस्"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"फिंगरप्रिन्ट प्रयोग गरी खोल्नुहोस्"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index be1735c..52b58b8 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Camera"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Telefoon"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Spraakassistent"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"Ontgrendelen"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Apparaat vergrendeld"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Wachten op vingerafdruk"</string>
@@ -291,7 +293,7 @@
<string name="accessibility_casting_turned_off" msgid="1387906158563374962">"Casten van scherm gestopt."</string>
<string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Werkmodus is onderbroken."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Werkmodus aan."</string>
- <string name="accessibility_quick_settings_work_mode_changed_off" msgid="2653550342355027441">"Werkmodus is uitgezet."</string>
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Werkmodus is onderbroken."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Werkmodus staat aan."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Databesparing staat uit."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Databesparing staat aan."</string>
@@ -1150,4 +1152,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"verifiëren"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"apparaat opgeven"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Gebruik vingerafdruk om te openen"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index 9a2cd80..20a66b3 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"କ୍ୟାମେରା"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"ଫୋନ୍"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"ଭଏସ୍ ସହାୟକ"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"ଅନଲକ୍ କରନ୍ତୁ"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"ଡିଭାଇସ୍ ଲକ୍ ହୋଇଯାଇଛି"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"ଟିପଚିହ୍ନ ପାଇଁ ଅପେକ୍ଷା କରୁଛି"</string>
@@ -289,11 +291,9 @@
<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_casting_turned_off" msgid="1387906158563374962">"ସ୍କ୍ରୀନ୍ କାଷ୍ଟ କରିବା ରହିଯାଇଛି।"</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"ୱାର୍କ ମୋଡକୁ ବିରତ କରାଯାଇଛି।"</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"ୱର୍କ ମୋଡ୍ ଅନ୍।"</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"ୱାର୍କ ମୋଡକୁ ବିରତ କରାଯାଇଛି।"</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"ୱର୍କ ମୋଡ୍କୁ ଅନ୍ କରାଯାଇଛି।"</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"ଡାଟା ସେଭର୍ ଅଫ୍ କରାଗଲା।"</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"ଡାଟା ସେଭର୍ ଅନ୍ କରାଗଲା।"</string>
@@ -412,8 +412,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"<xliff:g id="DATA_LIMIT">%s</xliff:g> ସୀମା"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"<xliff:g id="DATA_LIMIT">%s</xliff:g> ଚେତାବନୀ"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"ୱର୍କ ପ୍ରୋଫାଇଲ୍"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"ବିରତ କରାଯାଇଛି"</string>
<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>
@@ -672,12 +671,10 @@
<string name="wallet_title" msgid="5369767670735827105">"ୱାଲେଟ୍"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"ସବୁ ଦେଖାନ୍ତୁ"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"ପେମେଣ୍ଟ କରିବାକୁ ଅନଲକ୍ କରନ୍ତୁ"</string>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"ସେଟ୍ ଅପ୍ କରାଯାଇନାହିଁ"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ବ୍ୟବହାର କରିବାକୁ ଅନଲକ୍ କରନ୍ତୁ"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"ଆପଣଙ୍କ କାର୍ଡଗୁଡ଼ିକ ପାଇବାରେ ଏକ ସମସ୍ୟା ହୋଇଥିଲା। ଦୟାକରି ପରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ"</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"ସ୍କ୍ରିନ୍ ଲକ୍ ସେଟିଂସ୍"</string>
<string name="status_bar_work" msgid="5238641949837091056">"ୱର୍କ ପ୍ରୋଫାଇଲ୍"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"ଏରୋପ୍ଲେନ୍ ମୋଡ୍"</string>
<string name="add_tile" msgid="6239678623873086686">"ଟାଇଲ୍ ଯୋଡ଼ନ୍ତୁ"</string>
@@ -867,8 +864,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"ଚାଲୁ"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"ବନ୍ଦ"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"ଅନୁପଲବ୍ଧ"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"ଅକ୍ଷମ କରାଯାଇଛି"</string>
<string name="nav_bar" msgid="4642708685386136807">"ନାଭିଗେଶନ୍ ବାର୍"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"ଲେଆଉଟ୍"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"ସମ୍ପୂର୍ଣ୍ଣ ବାମ ବଟନ୍ ପ୍ରକାର"</string>
@@ -1156,4 +1152,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"ପ୍ରମାଣୀକରଣ କରନ୍ତୁ"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"ଡିଭାଇସ୍ ବିଷୟରେ ସୂଚନା ଲେଖନ୍ତୁ"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"ଖୋଲିବାକୁ ଟିପଚିହ୍ନ ବ୍ୟବହାର କରନ୍ତୁ"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index bc9b2ee..df2caea 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"ਕੈਮਰਾ"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"ਫ਼ੋਨ ਕਰੋ"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"ਅਵਾਜ਼ੀ ਸਹਾਇਕ"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"ਅਣਲਾਕ ਕਰੋ"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"ਡੀਵਾਈਸ ਲਾਕ ਹੈ"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਦੀ ਉਡੀਕ ਹੋ ਰਹੀ ਹੈ"</string>
@@ -289,11 +291,9 @@
<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_casting_turned_off" msgid="1387906158563374962">"ਸਕ੍ਰੀਨ ਜੋੜਨਾ ਬੰਦ ਹੋਇਆ।"</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"ਕਾਰਜ ਮੋਡ ਰੁਕਿਆ ਹੋਇਆ ਹੈ।"</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"ਕੰਮ ਮੋਡ ਚਾਲੂ ਹੈ।"</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"ਕਾਰਜ ਮੋਡ ਰੁਕਿਆ ਹੋਇਆ ਹੈ।"</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"ਕੰਮ ਮੋਡ ਚਾਲੂ ਕੀਤਾ ਗਿਆ।"</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"ਡਾਟਾ ਸੇਵਰ ਬੰਦ ਕੀਤਾ ਗਿਆ।"</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"ਡਾਟਾ ਸੇਵਰ ਚਾਲੂ ਕੀਤਾ ਗਿਆ।"</string>
@@ -412,8 +412,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"<xliff:g id="DATA_LIMIT">%s</xliff:g> ਸੀਮਾ"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"<xliff:g id="DATA_LIMIT">%s</xliff:g> ਚਿਤਾਵਨੀ"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"ਰੁਕਿਆ ਹੋਇਆ ਹੈ"</string>
<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>
@@ -473,14 +472,10 @@
<string name="interruption_level_none_twoline" msgid="8579382742855486372">"ਕੁਲ \n ਚੁੱਪੀ"</string>
<string name="interruption_level_priority_twoline" msgid="8523482736582498083">"ਕੇਵਲ\nਤਰਜੀਹੀ"</string>
<string name="interruption_level_alarms_twoline" msgid="2045067991335708767">"ਕੇਵਲ\nਅਲਾਰਮ"</string>
- <!-- no translation found for keyguard_indication_charging_time_wireless (577856646141738675) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time (6492711711891071502) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_fast (8390311020603859480) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_slowly (301936949731705417) -->
- <skip />
+ <string name="keyguard_indication_charging_time_wireless" msgid="577856646141738675">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ਬਿਨਾਂ ਤਾਰ ਤੋਂ ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ਵਿੱਚ ਪੂਰਾ ਚਾਰਜ ਹੋਵੇਗਾ"</string>
+ <string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ਵਿੱਚ ਪੂਰਾ ਚਾਰਜ ਹੋਵੇਗਾ"</string>
+ <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ਤੇਜ਼ ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ਵਿੱਚ ਪੂਰਾ ਚਾਰਜ ਹੋਵੇਗਾ"</string>
+ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ਹੌਲੀ ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ਵਿੱਚ ਪੂਰਾ ਚਾਰਜ ਹੋਵੇਗਾ"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ਵਰਤੋਂਕਾਰ ਸਵਿੱਚ ਕਰੋ"</string>
<string name="accessibility_multi_user_switch_switcher_with_current" msgid="5759855008166759399">"ਵਰਤੋਂਕਾਰ, ਵਰਤਮਾਨ ਵਰਤੋਂਕਾਰ ਸਵਿੱਚ ਕਰੋ <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_inactive" msgid="383168614528618402">"ਮੌਜੂਦਾ ਉਪਭੋਗਤਾ <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -676,12 +671,10 @@
<string name="wallet_title" msgid="5369767670735827105">"ਵਾਲੇਟ"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"ਸਭ ਦਿਖਾਓ"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"ਭੁਗਤਾਨ ਕਰਨ ਲਈ ਅਣਲਾਕ ਕਰੋ"</string>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"ਸੈੱਟਅੱਪ ਨਹੀਂ ਕੀਤਾ ਗਿਆ"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ਵਰਤਣ ਲਈ ਅਣਲਾਕ ਕਰੋ"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"ਤੁਹਾਡੇ ਕਾਰਡ ਪ੍ਰਾਪਤ ਕਰਨ ਵਿੱਚ ਕੋਈ ਸਮੱਸਿਆ ਆਈ, ਕਿਰਪਾ ਕਰਕੇ ਬਾਅਦ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ"</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"ਲਾਕ ਸਕ੍ਰੀਨ ਸੈਟਿੰਗਾਂ"</string>
<string name="status_bar_work" msgid="5238641949837091056">"ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"ਹਵਾਈ-ਜਹਾਜ਼ ਮੋਡ"</string>
<string name="add_tile" msgid="6239678623873086686">"ਟਾਇਲ ਸ਼ਾਮਲ ਕਰੋ"</string>
@@ -871,8 +864,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"ਚਾਲੂ"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"ਬੰਦ"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"ਅਣਉਪਲਬਧ"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"ਬੰਦ ਹੈ"</string>
<string name="nav_bar" msgid="4642708685386136807">"ਦਿਸ਼ਾ-ਨਿਰਦੇਸ਼ ਪੱਟੀ"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"ਖਾਕਾ"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"ਵਧੇਰੇ ਖੱਬੇ ਬਟਨ ਕਿਸਮ"</string>
@@ -1160,4 +1152,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"ਪ੍ਰਮਾਣਿਤ ਕਰੋ"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"ਡੀਵਾਈਸ ਵਿੱਚ ਦਾਖਲ ਹੋਵੋ"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"ਖੋਲ੍ਹਣ ਲਈ ਫਿੰਗਰਪ੍ਰਿੰਟ ਵਰਤੋ"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 3c6578e..1a9c868 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Aparat"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Telefon"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Asystent głosowy"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"Odblokuj"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Urządzenie zablokowane"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Czekam na odcisk palca"</string>
@@ -289,11 +291,9 @@
<string name="accessibility_quick_settings_hotspot_changed_off" msgid="7002061268910095176">"Mobilny hotspot został wyłączony."</string>
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2576895346762408840">"Mobilny hotspot został włączony."</string>
<string name="accessibility_casting_turned_off" msgid="1387906158563374962">"Zatrzymano przesyłanie ekranu."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Wstrzymano tryb pracy."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Tryb pracy włączony."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Wstrzymano tryb pracy."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Tryb pracy włączony."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Oszczędzanie danych jest wyłączone."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Oszczędzanie danych jest włączone."</string>
@@ -416,8 +416,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"Limit <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"Ostrzeżenie: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"Profil służbowy"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"Wstrzymano"</string>
<string name="quick_settings_night_display_label" msgid="8180030659141778180">"Podświetlenie nocne"</string>
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Włącz o zachodzie"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"Do wschodu słońca"</string>
@@ -678,12 +677,10 @@
<string name="wallet_title" msgid="5369767670735827105">"Portfel"</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>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Nie skonfigurowano"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Odblokuj, aby użyć"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Podczas pobierania kart wystąpił problem. Spróbuj ponownie później."</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Ustawienia ekranu blokady"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Profil służbowy"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Tryb samolotowy"</string>
<string name="add_tile" msgid="6239678623873086686">"Dodaj nazwę"</string>
@@ -877,8 +874,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"Wł."</string>
<string name="switch_bar_off" msgid="5669805115416379556">"Wył."</string>
<string name="tile_unavailable" msgid="3095879009136616920">"Niedostępne"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"Wyłączono"</string>
<string name="nav_bar" msgid="4642708685386136807">"Pasek nawigacji"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"Układ"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"Typ dodatkowego lewego przycisku"</string>
@@ -1168,4 +1164,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"uwierzytelnij"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"otwórz urządzenie"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"By otworzyć, użyj odcisku palca"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 8228c0c..fa10f0f 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -136,6 +136,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Câmera"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Telefone"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Assistência de voz"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"Carteira"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"Desbloquear"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Dispositivo bloqueado"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Aguardando impressão digital"</string>
@@ -291,7 +292,7 @@
<string name="accessibility_casting_turned_off" msgid="1387906158563374962">"A transmissão de tela foi interrompida."</string>
<string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Modo de trabalho pausado."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Modo de trabalho ativado."</string>
- <string name="accessibility_quick_settings_work_mode_changed_off" msgid="2653550342355027441">"O modo de trabalho foi pausado."</string>
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Modo de trabalho pausado."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Modo de trabalho ativado."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Economia de dados desativada."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Economia de dados ativada."</string>
@@ -1150,4 +1151,6 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"autenticar"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"acessar o dispositivo"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Use a impressão digital para abrir"</string>
+ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autenticação obrigatória. Toque no sensor de impressão digital para autenticar."</string>
+ <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Chamada em andamento"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index afebc31..1723de6 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Câmara"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Telemóvel"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Assistente de voz"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"Desbloquear"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Dispositivo bloqueado"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"A aguardar a impressão digital…"</string>
@@ -289,11 +291,9 @@
<string name="accessibility_quick_settings_hotspot_changed_off" msgid="7002061268910095176">"Zona Wi-Fi móvel desligada."</string>
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2576895346762408840">"Zona Wi-Fi móvel ligada."</string>
<string name="accessibility_casting_turned_off" msgid="1387906158563374962">"Transmissão do ecrã interrompida."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Modo de trabalho colocado em pausa."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Modo de trabalho ativado."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Modo de trabalho colocado em pausa."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"O modo de trabalho foi ativado."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Poupança de dados desativada."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Poupança de dados ativada."</string>
@@ -412,8 +412,7 @@
<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="2754212289804324685">"Perfil de trabalho"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"Em pausa"</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>
@@ -672,12 +671,10 @@
<string name="wallet_title" msgid="5369767670735827105">"Carteira"</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>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Não configurado"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Desbloquear para utilizar"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Ocorreu um problema ao obter os seus cartões. Tente novamente mais tarde."</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Definições do ecrã de bloqueio"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Perfil de trabalho"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Modo de avião"</string>
<string name="add_tile" msgid="6239678623873086686">"Adicionar mosaico"</string>
@@ -867,8 +864,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"Ativado"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"Desativado"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"Indisponível"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"Desativado"</string>
<string name="nav_bar" msgid="4642708685386136807">"Barra de navegação"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"Esquema"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"Tipo de botão esquerdo adicional"</string>
@@ -1156,4 +1152,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"autenticar"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"entrar no dispositivo"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Utilize a impressão digital para abrir"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 8228c0c..fa10f0f 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -136,6 +136,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Câmera"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Telefone"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Assistência de voz"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"Carteira"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"Desbloquear"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Dispositivo bloqueado"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Aguardando impressão digital"</string>
@@ -291,7 +292,7 @@
<string name="accessibility_casting_turned_off" msgid="1387906158563374962">"A transmissão de tela foi interrompida."</string>
<string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Modo de trabalho pausado."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Modo de trabalho ativado."</string>
- <string name="accessibility_quick_settings_work_mode_changed_off" msgid="2653550342355027441">"O modo de trabalho foi pausado."</string>
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Modo de trabalho pausado."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Modo de trabalho ativado."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Economia de dados desativada."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Economia de dados ativada."</string>
@@ -1150,4 +1151,6 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"autenticar"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"acessar o dispositivo"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Use a impressão digital para abrir"</string>
+ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autenticação obrigatória. Toque no sensor de impressão digital para autenticar."</string>
+ <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Chamada em andamento"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 87f9e98..1fb5514 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Cameră foto"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Telefon"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Asistent vocal"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"Deblocați"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Dispozitiv blocat"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Se așteaptă amprenta"</string>
@@ -289,11 +291,9 @@
<string name="accessibility_quick_settings_hotspot_changed_off" msgid="7002061268910095176">"Hotspotul mobil este dezactivat."</string>
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2576895346762408840">"Hotspotul mobil este activat."</string>
<string name="accessibility_casting_turned_off" msgid="1387906158563374962">"Transmiterea ecranului a fost oprită."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Modul de lucru s-a întrerupt."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Modul de lucru este activat."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Modul de lucru a fost întrerupt."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Modul de lucru a fost activat."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Economizorul de date a fost dezactivat."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Economizorul de date a fost activat."</string>
@@ -414,8 +414,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"Limită de <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"Avertizare: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"Profil de serviciu"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"Întrerupt"</string>
<string name="quick_settings_night_display_label" msgid="8180030659141778180">"Lumină de noapte"</string>
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Activată la apus"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"Până la răsărit"</string>
@@ -475,14 +474,10 @@
<string name="interruption_level_none_twoline" msgid="8579382742855486372">"Niciun\nsunet"</string>
<string name="interruption_level_priority_twoline" msgid="8523482736582498083">"Numai\ncu prioritate"</string>
<string name="interruption_level_alarms_twoline" msgid="2045067991335708767">"Numai\nalarme"</string>
- <!-- no translation found for keyguard_indication_charging_time_wireless (577856646141738675) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time (6492711711891071502) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_fast (8390311020603859480) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_slowly (301936949731705417) -->
- <skip />
+ <string name="keyguard_indication_charging_time_wireless" msgid="577856646141738675">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Se încarcă wireless • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> până la încărcarea completă"</string>
+ <string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Se încarcă • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> până la încărcarea completă"</string>
+ <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Se încarcă rapid • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> până la încărcarea completă"</string>
+ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Se încarcă lent • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> până la încărcarea completă"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Comutați între utilizatori"</string>
<string name="accessibility_multi_user_switch_switcher_with_current" msgid="5759855008166759399">"Schimbați utilizatorul (utilizator actual <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>)"</string>
<string name="accessibility_multi_user_switch_inactive" msgid="383168614528618402">"Utilizator actual <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -679,12 +674,10 @@
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</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>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Neconfigurat"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Deblocați pentru a folosi"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"A apărut o problemă la preluarea cardurilor. Încercați din nou mai târziu"</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Setările ecranului de blocare"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Profil de serviciu"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Mod Avion"</string>
<string name="add_tile" msgid="6239678623873086686">"Adăugați o casetă"</string>
@@ -876,8 +869,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"Activat"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"Dezactivați"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"Indisponibil"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"Dezactivat"</string>
<string name="nav_bar" msgid="4642708685386136807">"Bară de navigare"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"Aspect"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"Tip de buton din extrema stângă"</string>
@@ -1166,4 +1158,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"Autentificați-vă"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"Accesați dispozitivul"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Folosiți amprenta ca să deschideți"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index c64d557..805e16e 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Камера"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Телефон."</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Аудиоподсказки"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"Разблокировать."</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Устройство заблокировано"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Отсканируйте отпечаток пальца"</string>
@@ -289,11 +291,9 @@
<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_casting_turned_off" msgid="1387906158563374962">"Трансляция прекращена."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Рабочий режим отключен."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Рабочий режим включен."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Рабочий режим отключен."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Рабочий режим включен."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Режим экономии трафика отключен."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Режим экономии трафика включен."</string>
@@ -416,8 +416,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"Ограничение: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"Предупреждение: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"Рабочий профиль"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"Приостановлен"</string>
<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>
@@ -477,14 +476,10 @@
<string name="interruption_level_none_twoline" msgid="8579382742855486372">"Полная\nтишина"</string>
<string name="interruption_level_priority_twoline" msgid="8523482736582498083">"Только\nважные"</string>
<string name="interruption_level_alarms_twoline" msgid="2045067991335708767">"Только\nбудильник"</string>
- <!-- no translation found for keyguard_indication_charging_time_wireless (577856646141738675) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time (6492711711891071502) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_fast (8390311020603859480) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_slowly (301936949731705417) -->
- <skip />
+ <string name="keyguard_indication_charging_time_wireless" msgid="577856646141738675">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Беспроводная зарядка • Осталось <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Зарядка • Осталось <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Быстрая зарядка • Осталось <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Медленная зарядка • Осталось <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Сменить пользователя."</string>
<string name="accessibility_multi_user_switch_switcher_with_current" msgid="5759855008166759399">"Сменить аккаунт. Вход выполнен под именем <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>."</string>
<string name="accessibility_multi_user_switch_inactive" msgid="383168614528618402">"Выбран аккаунт пользователя <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -682,12 +677,10 @@
<string name="wallet_title" msgid="5369767670735827105">"Кошелек"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Показать все"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Разблокировать для оплаты"</string>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Не настроено"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Разблокировать для использования"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Не удалось получить информацию о картах. Повторите попытку позже."</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Настройки заблокированного экрана"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Рабочий профиль"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Режим полета"</string>
<string name="add_tile" msgid="6239678623873086686">"Добавить кнопку быстрого доступа"</string>
@@ -881,8 +874,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"Включено"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"Отключено"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"Недоступно"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"Отключено"</string>
<string name="nav_bar" msgid="4642708685386136807">"Панель навигации"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"Расположение кнопок"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"Дополнительный тип кнопки \"Влево\""</string>
@@ -1172,4 +1164,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"выполнить аутентификацию"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"указать устройство"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Используйте отпечаток пальца для входа."</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index 961fe17..71e9077 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -136,6 +136,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"කැමරාව"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"දුරකථනය"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"හඬ සහාය"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"පසුම්බිය"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"අඟුල අරින්න"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"උපාංගය අගුලු දමා ඇත"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"ඇඟිලි සලකුණ සඳහා බලා සිටිමින්"</string>
@@ -289,11 +290,9 @@
<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_casting_turned_off" msgid="1387906158563374962">"තිරය විකාශය කිරීම නැවත් වන ලදි."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"කාර්යාල ප්රකාරය විරාම කරන ලදි."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"වැඩ ප්රකාරය ක්රියාත්මකයි."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"කාර්යාල ප්රකාරය විරාම කරන ලදි."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"වැඩ ප්රකාරය ක්රියාත්මක කරන ලදී."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"දත්ත සුරැකුම ක්රියාවිරහිත කරන ලදී."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"දත්ත සුරැකුම ක්රියාත්මක කරන ලදී."</string>
@@ -412,8 +411,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"<xliff:g id="DATA_LIMIT">%s</xliff:g> සීමිත"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"<xliff:g id="DATA_LIMIT">%s</xliff:g> අවවාද කිරීම"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"කාර්යාල පැතිකඩ"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"විරාම කරන ලදි"</string>
<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>
@@ -672,12 +670,10 @@
<string name="wallet_title" msgid="5369767670735827105">"පසුම්බිය"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"සියල්ල පෙන්වන්න"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"ගෙවීමට අගුලු හරින්න"</string>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"පිහිටුවා නැත"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"භාවිත කිරීමට අගුලු හරින්න"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"ඔබගේ කාඩ්පත ලබා ගැනීමේ ගැටලුවක් විය, කරුණාකර පසුව නැවත උත්සාහ කරන්න"</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"අගුලු තිර සැකසීම්"</string>
<string name="status_bar_work" msgid="5238641949837091056">"කාර්යාල පැතිකඩ"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"ගුවන්යානා ප්රකාරය"</string>
<string name="add_tile" msgid="6239678623873086686">"ටයිල් එක් කරන්න"</string>
@@ -867,8 +863,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"ක්රියාත්මකයි"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"ක්රියාවිරහිතයි"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"ලබා ගත නොහැකිය"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"අබලයි"</string>
<string name="nav_bar" msgid="4642708685386136807">"සංචලන තීරුව"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"පිරිසැලසුම"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"අමතර වම් බොත්තම් වර්ගය"</string>
@@ -1156,4 +1151,6 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"සත්යාපනය කරන්න"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"උපාංගය ඇතුළු කරන්න"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"විවෘත කිරීමට ඇඟිලි සලකුණ භාවිත කරන්න"</string>
+ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"සත්යාපනය අවශ්යයි. සත්යාපනය කිරීමට ඇඟිලි සලකුණු සංවේදකය ස්පර්ශ කරන්න."</string>
+ <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"ක්රියාත්මක වන දුරකථන ඇමතුම"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 407ad62..79e1cfb 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Fotoaparát"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Telefón"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Hlasový asistent"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"Odomknúť"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Zariadenie je uzamknuté"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Čaká sa na odtlačok prsta"</string>
@@ -291,7 +293,7 @@
<string name="accessibility_casting_turned_off" msgid="1387906158563374962">"Prenášanie bolo zastavené."</string>
<string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Pracovný režim je pozastavený."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Pracovný režim zapnutý"</string>
- <string name="accessibility_quick_settings_work_mode_changed_off" msgid="2653550342355027441">"Pracovný režim bol pozastavený."</string>
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Pracovný režim je pozastavený."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Pracovný režim je zapnutý."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Šetrič dát bol vypnutý."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Šetrič dát bol zapnutý."</string>
@@ -1125,7 +1127,7 @@
<string name="basic_status" msgid="2315371112182658176">"Otvorená konverzácia"</string>
<string name="select_conversation_title" msgid="6716364118095089519">"Miniaplikácie konverzácií"</string>
<string name="select_conversation_text" msgid="3376048251434956013">"Klepnite na konverzáciu a pridajte ju tak na plochu"</string>
- <string name="no_conversations_text" msgid="7362374212649891057">"Sem sa vráťte, keď dostanete nejaké správy"</string>
+ <string name="no_conversations_text" msgid="7362374212649891057">"Vráťte sa sem, až dostanete nejaké správy"</string>
<string name="priority_conversations" msgid="3967482288896653039">"Prioritné konverzácie"</string>
<string name="recent_conversations" msgid="8531874684782574622">"Nedávne konverzácie"</string>
<string name="okay" msgid="6490552955618608554">"OK"</string>
@@ -1146,7 +1148,7 @@
<string name="audio_status" msgid="4237055636967709208">"Počúvam"</string>
<string name="game_status" msgid="1340694320630973259">"Hrá sa hra"</string>
<string name="empty_user_name" msgid="3389155775773578300">"Priatelia"</string>
- <string name="empty_status" msgid="5938893404951307749">"Porozprávajme sa."</string>
+ <string name="empty_status" msgid="5938893404951307749">"Poďme sa rozprávať."</string>
<string name="status_before_loading" msgid="1500477307859631381">"Obsah sa čoskoro zobrazí"</string>
<string name="missed_call" msgid="4228016077700161689">"Zmeškaný hovor"</string>
<string name="messages_count_overflow_indicator" msgid="7850934067082006043">"<xliff:g id="NUMBER">%d</xliff:g>+"</string>
@@ -1162,4 +1164,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"overte"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"vstúpte do zariadenia"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Otvorte odtlačkom prsta"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index f11db07..6500e05 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Fotoaparat"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Telefon"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Glasovni pomočnik"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"Odkleni"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Naprava je zaklenjena."</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Čakanje na prstni odtis"</string>
@@ -289,11 +291,9 @@
<string name="accessibility_quick_settings_hotspot_changed_off" msgid="7002061268910095176">"Mobilna dostopna točka je izklopljena."</string>
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2576895346762408840">"Mobilna dostopna točka je vklopljena."</string>
<string name="accessibility_casting_turned_off" msgid="1387906158563374962">"Predvajanje zaslona je ustavljeno."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Način za delo je začasno zaustavljen."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Način za delo vklopljen."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Način za delo je začasno zaustavljen."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Način za delo je vklopljen."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Varčevanje s podatki je izklopljeno."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Varčevanje s podatki je vklopljeno."</string>
@@ -416,8 +416,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"Omejitev: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"Opozorilo – <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"Delovni profil"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"Zaustavljeno"</string>
<string name="quick_settings_night_display_label" msgid="8180030659141778180">"Nočna svetloba"</string>
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Ob sončnem zahodu"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"Do sončnega vzhoda"</string>
@@ -477,14 +476,10 @@
<string name="interruption_level_none_twoline" msgid="8579382742855486372">"Popolna\ntišina"</string>
<string name="interruption_level_priority_twoline" msgid="8523482736582498083">"Samo\nprednostno"</string>
<string name="interruption_level_alarms_twoline" msgid="2045067991335708767">"Samo\nalarmi"</string>
- <!-- no translation found for keyguard_indication_charging_time_wireless (577856646141738675) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time (6492711711891071502) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_fast (8390311020603859480) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_slowly (301936949731705417) -->
- <skip />
+ <string name="keyguard_indication_charging_time_wireless" msgid="577856646141738675">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Brezžično polnjenje • Napolnjeno čez <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Polnjenje • Napolnjeno čez <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Hitro polnjenje • Napolnjeno čez <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Počasno polnjenje • Napolnjeno čez <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Preklop med uporabniki"</string>
<string name="accessibility_multi_user_switch_switcher_with_current" msgid="5759855008166759399">"Preklop med uporabniki, trenutni uporabnik <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_inactive" msgid="383168614528618402">"Trenutni uporabnik: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -682,12 +677,10 @@
<string name="wallet_title" msgid="5369767670735827105">"Denarnica"</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>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Ni nastavljeno"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Odklenite za uporabo"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Pri pridobivanju kartic je prišlo do težave. Poskusite znova pozneje."</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Nastavitve zaklepanja zaslona"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Profil za Android Work"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Način za letalo"</string>
<string name="add_tile" msgid="6239678623873086686">"Dodajanje ploščice"</string>
@@ -881,8 +874,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"Vklopljeno"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"Izklopljeno"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"Ni na voljo"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"Onemogočeno"</string>
<string name="nav_bar" msgid="4642708685386136807">"Vrstica za krmarjenje"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"Postavitev"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"Vrsta dodatnega levega gumba"</string>
@@ -1172,4 +1164,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"preverjanje pristnosti"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"vstop v napravo"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Odprite s prstnim odtisom"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index d44bd22..9df3c98 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Kamera"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Telefoni"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Ndihma zanore"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"Shkyç"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Pajisja është e kyçur"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Në pritje për gjurmën e gishtit"</string>
@@ -292,7 +294,7 @@
<!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
<skip />
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Modaliteti i punës është i aktivizuar."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
+ <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (6422896967647049692) -->
<skip />
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Modaliteti i punës është i aktivizuar."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Kursyesi i të dhënave është çaktivizuar."</string>
@@ -1156,4 +1158,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"për ta vërtetuar"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"për të hyrë në pajisje"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Përdor gjurmën e gishtit për ta hapur"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 93fb30f..055acfa 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Камера"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Телефон"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Гласовна помоћ"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"Откључајте"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Уређај је закључан"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Чека се отисак прста"</string>
@@ -289,11 +291,9 @@
<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_casting_turned_off" msgid="1387906158563374962">"Пребацивање екрана је заустављено."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Пословни режим је паузиран."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Режим рада је укључен."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Пословни режим је паузиран."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Режим рада је укључен."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Уштеда података је искључена."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Уштеда података је укључена."</string>
@@ -414,8 +414,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"Ограничење од <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"Упозорење за <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"Пословни профил"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"Паузирано"</string>
<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>
@@ -675,12 +674,10 @@
<string name="wallet_title" msgid="5369767670735827105">"Новчаник"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Прикажи све"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Откључај ради плаћања"</string>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Није подешено"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Откључај ради коришћења"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Дошло је до проблема при преузимању картица. Пробајте поново касније"</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Подешавања закључаног екрана"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Пословни профил"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Режим рада у авиону"</string>
<string name="add_tile" msgid="6239678623873086686">"Додај плочицу"</string>
@@ -872,8 +869,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"Укључено"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"Искључено"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"Недоступно"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"Онемогућено"</string>
<string name="nav_bar" msgid="4642708685386136807">"Трака за навигацију"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"Распоред"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"Додатни тип левог дугмета"</string>
@@ -1146,7 +1142,7 @@
<string name="audio_status" msgid="4237055636967709208">"Слуша се"</string>
<string name="game_status" msgid="1340694320630973259">"Игра се"</string>
<string name="empty_user_name" msgid="3389155775773578300">"Пријатељи"</string>
- <string name="empty_status" msgid="5938893404951307749">"Ћаскамо вечерас!"</string>
+ <string name="empty_status" msgid="5938893404951307749">"Ћаскамо вечерас?"</string>
<string name="status_before_loading" msgid="1500477307859631381">"Садржај ће се ускоро појавити"</string>
<string name="missed_call" msgid="4228016077700161689">"Пропуштен позив"</string>
<string name="messages_count_overflow_indicator" msgid="7850934067082006043">"<xliff:g id="NUMBER">%d</xliff:g>+"</string>
@@ -1162,4 +1158,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"потврдите идентитет"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"унесите уређај"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Отворите помоћу отиска прста"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 3e7e1b1..a74b2ec 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Kamera"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Mobil"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Röstassistent"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"Lås upp"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Enheten är låst"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Väntar på fingeravtryck"</string>
@@ -289,11 +291,9 @@
<string name="accessibility_quick_settings_hotspot_changed_off" msgid="7002061268910095176">"Den mobila surfzonen har inaktiverats."</string>
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2576895346762408840">"Den mobila surfzonen har aktiverats."</string>
<string name="accessibility_casting_turned_off" msgid="1387906158563374962">"Castningen av skärmen har stoppats."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Jobbläget har pausats."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Arbetsläget aktiverat."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Jobbläget har pausats."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Arbetsläget har aktiverats."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Databesparing har inaktiverats."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Databesparing har aktiverats."</string>
@@ -412,8 +412,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"Gräns: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"Varning <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"Jobbprofil"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"Pausat"</string>
<string name="quick_settings_night_display_label" msgid="8180030659141778180">"Nattljus"</string>
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"På från solnedgången"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"Till soluppgången"</string>
@@ -672,12 +671,10 @@
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</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>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Har inte konfigurerats"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Lås upp för att använda"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Det gick inte att hämta dina kort. Försök igen senare."</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Inställningar för låsskärm"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Jobbprofil"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Flygplansläge"</string>
<string name="add_tile" msgid="6239678623873086686">"Lägg till en ruta"</string>
@@ -867,8 +864,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"På"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"Av"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"Inte tillgängligt"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"Inaktiverat"</string>
<string name="nav_bar" msgid="4642708685386136807">"Navigeringsfält"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"Layout"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"Knapptyp för extra vänster"</string>
@@ -1121,7 +1117,7 @@
<string name="select_conversation_text" msgid="3376048251434956013">"Tryck på en konversation för att lägga till den på startskärmen"</string>
<string name="no_conversations_text" msgid="7362374212649891057">"Besök den här sidan igen när du har fått meddelanden"</string>
<string name="priority_conversations" msgid="3967482288896653039">"Prioriterade konversationer"</string>
- <string name="recent_conversations" msgid="8531874684782574622">"Aktuella konversationer"</string>
+ <string name="recent_conversations" msgid="8531874684782574622">"Senaste konversationerna"</string>
<string name="okay" msgid="6490552955618608554">"Okej"</string>
<string name="timestamp" msgid="6577851592534538533">"För <xliff:g id="DURATION">%1$s</xliff:g> sedan"</string>
<string name="less_than_timestamp" msgid="6598972791137724517">"Mindre än <xliff:g id="DURATION">%1$s</xliff:g> sedan"</string>
@@ -1156,4 +1152,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"autentisera"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"ange enhet"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Öppna med fingeravtryck"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index a591d00..e60d575 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -136,6 +136,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Kamera"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Simu"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Mapendekezo ya Sauti"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"Fungua"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Kifaa kimefungwa"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Inasubiri alama ya kidole"</string>
@@ -289,11 +290,9 @@
<string name="accessibility_quick_settings_hotspot_changed_off" msgid="7002061268910095176">"Mtandaopepe unahamishika umezimwa."</string>
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2576895346762408840">"Mtandaopepe unaohamishika umewashwa."</string>
<string name="accessibility_casting_turned_off" msgid="1387906158563374962">"Utumaji wa skrini umesitishwa."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Hali ya kazini imesimamishwa."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Hali ya kazi imewashwa."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Hali ya kazini imesimamishwa."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Hali ya kazi imewashwa."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Kiokoa Data kimezimwa."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Kiokoa Data kimewashwa."</string>
@@ -412,8 +411,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"kikomo <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"Onyo <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"Wasifu wa kazini"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"Imesimamishwa"</string>
<string name="quick_settings_night_display_label" msgid="8180030659141778180">"Mwanga wa Usiku"</string>
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Itawashwa machweo"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"Hadi macheo"</string>
@@ -473,14 +471,10 @@
<string name="interruption_level_none_twoline" msgid="8579382742855486372">"Kimya\nkabisa"</string>
<string name="interruption_level_priority_twoline" msgid="8523482736582498083">"Kipaumbele\npekee"</string>
<string name="interruption_level_alarms_twoline" msgid="2045067991335708767">"Kengele\npekee"</string>
- <!-- no translation found for keyguard_indication_charging_time_wireless (577856646141738675) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time (6492711711891071502) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_fast (8390311020603859480) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_slowly (301936949731705417) -->
- <skip />
+ <string name="keyguard_indication_charging_time_wireless" msgid="577856646141738675">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> Inachaji bila kutumia waya • Itajaa baada ya <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Inachaji • Itajaa baada ya <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Inachaji kwa kasi • Itajaa baada ya <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Inachaji polepole • Itajaa baada ya <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Badili mtumiaji"</string>
<string name="accessibility_multi_user_switch_switcher_with_current" msgid="5759855008166759399">"Badili mtumiaji, mtumiaji wa sasa <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_inactive" msgid="383168614528618402">"Mtumiaji wa sasa <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -676,12 +670,10 @@
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</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>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Haijawekwa"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Fungua ili utumie"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Hitilafu imetokea wakati wa kuleta kadi zako, tafadhali jaribu tena baadaye"</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Mipangilio ya kufunga skrini"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Wasifu wa kazini"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Hali ya ndegeni"</string>
<string name="add_tile" msgid="6239678623873086686">"Ongeza kigae"</string>
@@ -871,8 +863,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"Imewashwa"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"Imezimwa"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"Hakipatikani"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"Imezimwa"</string>
<string name="nav_bar" msgid="4642708685386136807">"Sehemu ya viungo muhimu"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"Mpangilio"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"Aina ya kitufe cha kushoto cha ziada"</string>
@@ -1124,7 +1115,7 @@
<string name="select_conversation_title" msgid="6716364118095089519">"Wijeti za mazungumzo"</string>
<string name="select_conversation_text" msgid="3376048251434956013">"Gusa mazungumzo ili uyaweke kwenye Skrini yako ya kwanza"</string>
<string name="no_conversations_text" msgid="7362374212649891057">"Angalia hapa tena utakapopokea ujumbe"</string>
- <string name="priority_conversations" msgid="3967482288896653039">"Mazungumzo ya kipaumbele"</string>
+ <string name="priority_conversations" msgid="3967482288896653039">"Mazungumzo yenye kipaumbele"</string>
<string name="recent_conversations" msgid="8531874684782574622">"Mazungumzo ya hivi majuzi"</string>
<string name="okay" msgid="6490552955618608554">"Sawa"</string>
<string name="timestamp" msgid="6577851592534538533">"<xliff:g id="DURATION">%1$s</xliff:g> zilizopita"</string>
@@ -1160,4 +1151,6 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"thibitisha"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"weka kifaa"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Tumia alama ya kidole kufungua"</string>
+ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Uthibitishaji unahitajika. Gusa kitambua alama ya kidole ili uthibitishe."</string>
+ <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Simu inayoendelea"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index d616eab..0b56d3b 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"கேமரா"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"ஃபோன்"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"குரல் உதவி"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"திற"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"சாதனம் பூட்டப்பட்டுள்ளது"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"கைரேகைக்காகக் காத்திருக்கிறது"</string>
@@ -289,11 +291,9 @@
<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_casting_turned_off" msgid="1387906158563374962">"திரையை அனுப்புதல் நிறுத்தப்பட்டது."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"பணிப் பயன்முறை இடைநிறுத்தப்பட்டது."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"பணிப் பயன்முறை இயக்கப்பட்டுள்ளது."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"பணிப் பயன்முறை இடைநிறுத்தப்பட்டது."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"பணிப் பயன்முறை இயக்கப்பட்டது."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"டேட்டா சேமிப்பான் முடக்கப்பட்டது."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"டேட்டா சேமிப்பான் இயக்கப்பட்டது."</string>
@@ -412,8 +412,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"<xliff:g id="DATA_LIMIT">%s</xliff:g> வரம்பு"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"<xliff:g id="DATA_LIMIT">%s</xliff:g> எச்சரிக்கை"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"பணிக் கணக்கு"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"இடைநிறுத்தப்பட்டது"</string>
<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>
@@ -473,14 +472,10 @@
<string name="interruption_level_none_twoline" msgid="8579382742855486372">"அறிவிப்புகள்\nவேண்டாம்"</string>
<string name="interruption_level_priority_twoline" msgid="8523482736582498083">"முன்னுரிமைகள்\nமட்டும்"</string>
<string name="interruption_level_alarms_twoline" msgid="2045067991335708767">"அலாரங்கள்\nமட்டும்"</string>
- <!-- no translation found for keyguard_indication_charging_time_wireless (577856646141738675) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time (6492711711891071502) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_fast (8390311020603859480) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_slowly (301936949731705417) -->
- <skip />
+ <string name="keyguard_indication_charging_time_wireless" msgid="577856646141738675">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • வயர்லெஸ் முறையில் சார்ஜாகிறது • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> இல் முழுதும் சார்ஜாகும்"</string>
+ <string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • சார்ஜாகிறது • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> இல் முழுதும் சார்ஜாகும்"</string>
+ <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • வேகமாகச் சார்ஜாகிறது • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> இல் முழுதும் சார்ஜாகும்"</string>
+ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • மெதுவாக சார்ஜாகிறது • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> இல் முழுதும் சார்ஜாகும்"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"பயனரை மாற்று"</string>
<string name="accessibility_multi_user_switch_switcher_with_current" msgid="5759855008166759399">"பயனரை மாற்று, தற்போதைய பயனர் <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_inactive" msgid="383168614528618402">"தற்போதைய பயனர்: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -676,12 +671,10 @@
<string name="wallet_title" msgid="5369767670735827105">"வாலட்"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"அனைத்தையும் காட்டு"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"பணம் செலுத்த அன்லாக் செய்க"</string>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"அமைக்கப்படவில்லை"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"பயன்படுத்துவதற்கு அன்லாக் செய்க"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"உங்கள் கார்டுகளின் விவரங்களைப் பெறுவதில் சிக்கல் ஏற்பட்டது, பிறகு முயலவும்"</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"பூட்டுத் திரை அமைப்புகள்"</string>
<string name="status_bar_work" msgid="5238641949837091056">"பணிக் கணக்கு"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"விமானப் பயன்முறை"</string>
<string name="add_tile" msgid="6239678623873086686">"டைலைச் சேர்க்கும்"</string>
@@ -871,8 +864,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"ஆன்"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"ஆஃப்"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"இல்லை"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"முடக்கப்பட்டது"</string>
<string name="nav_bar" msgid="4642708685386136807">"வழிசெலுத்தல் பட்டி"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"தளவமைப்பு"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"கூடுதல் இடப்புற பட்டன் வகை"</string>
@@ -1160,4 +1152,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"அங்கீகரி"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"சாதனத்தைத் திற"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"கைரேகையைப் பயன்படுத்தி திறந்திடுங்கள்"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index 7d44b2b..7c797b7 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"కెమెరా"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"ఫోన్"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"వాయిస్ అసిస్టెంట్"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"అన్లాక్ చేయి"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"పరికరం లాక్ చేయబడింది"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"వేలిముద్ర కోసం వేచి ఉంది"</string>
@@ -289,10 +291,9 @@
<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_casting_turned_off" msgid="1387906158563374962">"స్క్రీన్ ప్రసారం ఆపివేయబడింది."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"వర్క్ మోడ్ పాజ్లో ఉంది."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"పని మోడ్ ఆన్లో ఉంది."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
+ <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (6422896967647049692) -->
<skip />
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"పని మోడ్ ఆన్ చేయబడింది."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"డేటా సేవర్ ఆఫ్ చేయబడింది."</string>
@@ -412,8 +413,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"<xliff:g id="DATA_LIMIT">%s</xliff:g> పరిమితి"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"<xliff:g id="DATA_LIMIT">%s</xliff:g> హెచ్చరిక"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"ఆఫీస్ ప్రొఫైల్"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"పాజ్ చేయబడింది"</string>
<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>
@@ -473,14 +473,10 @@
<string name="interruption_level_none_twoline" msgid="8579382742855486372">"మొత్తం\nనిశ్శబ్దం"</string>
<string name="interruption_level_priority_twoline" msgid="8523482736582498083">"ప్రాధాన్యమైనవి\nమాత్రమే"</string>
<string name="interruption_level_alarms_twoline" msgid="2045067991335708767">"అలారాలు\nమాత్రమే"</string>
- <!-- no translation found for keyguard_indication_charging_time_wireless (577856646141738675) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time (6492711711891071502) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_fast (8390311020603859480) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_slowly (301936949731705417) -->
- <skip />
+ <string name="keyguard_indication_charging_time_wireless" msgid="577856646141738675">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • వైర్ లేకుండా ఛార్జ్ అవుతోంది • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>లో పూర్తిగా ఛార్జ్ అవుతుంది"</string>
+ <string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ఛార్జ్ అవుతోంది • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>లో పూర్తిగా ఛార్జ్ అవుతుంది"</string>
+ <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • వేగంగా ఛార్జ్ అవుతోంది • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>లో పూర్తి ఛార్జ్"</string>
+ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • నెమ్మదిగా ఛార్జ్ అవుతోంది • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>లో పూర్తి ఛార్జ్"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"వినియోగదారుని మార్చు"</string>
<string name="accessibility_multi_user_switch_switcher_with_current" msgid="5759855008166759399">"వినియోగదారుని మార్చు, ప్రస్తుత వినియోగదారు <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_inactive" msgid="383168614528618402">"ప్రస్తుత వినియోగదారు <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -676,12 +672,10 @@
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"అన్నింటినీ చూపు"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"పే చేయడానికి అన్లాక్ చేయండి"</string>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"సెటప్ చేయలేదు"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ఉపయోగించడానికి అన్లాక్ చేయండి"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"మీ కార్డ్లను పొందడంలో సమస్య ఉంది, దయచేసి తర్వాత మళ్లీ ట్రై చేయండి"</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"లాక్ స్క్రీన్ సెట్టింగ్లు"</string>
<string name="status_bar_work" msgid="5238641949837091056">"ఆఫీస్ ప్రొఫైల్"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"ఎయిర్ప్లేన్ మోడ్"</string>
<string name="add_tile" msgid="6239678623873086686">"టైల్ను జోడించండి"</string>
@@ -871,8 +865,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"ఆన్"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"ఆఫ్ చేయి"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"అందుబాటులో లేదు"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"డిజేబుల్ చేయబడింది"</string>
<string name="nav_bar" msgid="4642708685386136807">"నావిగేషన్ బార్"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"లేఅవుట్"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"అత్యంత ఎడమ వైపు ఉన్న బటన్ రకం"</string>
@@ -1160,4 +1153,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"ప్రామాణీకరించండి"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"పరికరాన్ని ఎంటర్ చేయండి"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"తెరవడానికి వేలిముద్రను ఉపయోగించండి"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index ff216a4..e7c20d2 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"กล้องถ่ายรูป"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"โทรศัพท์"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"ตัวช่วยเสียง"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"ปลดล็อก"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"อุปกรณ์ถูกล็อก"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"กำลังรอลายนิ้วมือ"</string>
@@ -289,11 +291,9 @@
<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_casting_turned_off" msgid="1387906158563374962">"หยุดการส่งหน้าจอแล้ว"</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"โหมดการทำงานหยุดชั่วคราว"</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"โหมดการทำงานเปิดอยู่"</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"โหมดการทำงานหยุดชั่วคราว"</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"เปิดโหมดการทำงานแล้ว"</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"ปิดโปรแกรมประหยัดอินเทอร์เน็ตแล้ว"</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"เปิดโปรแกรมประหยัดอินเทอร์เน็ตแล้ว"</string>
@@ -412,8 +412,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"ขีดจำกัด <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"คำเตือน <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"โปรไฟล์งาน"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"หยุดชั่วคราว"</string>
<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>
@@ -473,14 +472,10 @@
<string name="interruption_level_none_twoline" msgid="8579382742855486372">"ปิดเสียง\nทั้งหมด"</string>
<string name="interruption_level_priority_twoline" msgid="8523482736582498083">"เฉพาะเรื่อง\nสำคัญ"</string>
<string name="interruption_level_alarms_twoline" msgid="2045067991335708767">"เฉพาะปลุก\nเท่านั้น"</string>
- <!-- no translation found for keyguard_indication_charging_time_wireless (577856646141738675) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time (6492711711891071502) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_fast (8390311020603859480) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_slowly (301936949731705417) -->
- <skip />
+ <string name="keyguard_indication_charging_time_wireless" msgid="577856646141738675">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • กำลังชาร์จแบบไร้สาย • จะเต็มในอีก <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • กำลังชาร์จ • จะเต็มในอีก <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • กำลังชาร์จอย่างเร็ว • จะเต็มในอีก <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • กำลังชาร์จอย่างช้าๆ • จะเต็มในอีก <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"สลับผู้ใช้"</string>
<string name="accessibility_multi_user_switch_switcher_with_current" msgid="5759855008166759399">"เปลี่ยนผู้ใช้จากผู้ใช้ปัจจุบัน <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_inactive" msgid="383168614528618402">"ผู้ใช้ปัจจุบัน <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -676,12 +671,10 @@
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"แสดงทั้งหมด"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"ปลดล็อกเพื่อชำระเงิน"</string>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"ไม่ได้ตั้งค่า"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ปลดล็อกเพื่อใช้"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"เกิดปัญหาในการดึงข้อมูลบัตรของคุณ โปรดลองอีกครั้งในภายหลัง"</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"การตั้งค่าหน้าจอล็อก"</string>
<string name="status_bar_work" msgid="5238641949837091056">"โปรไฟล์งาน"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"โหมดบนเครื่องบิน"</string>
<string name="add_tile" msgid="6239678623873086686">"เพิ่มไทล์"</string>
@@ -871,8 +864,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"เปิด"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"ปิด"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"ไม่มี"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"ปิดใช้"</string>
<string name="nav_bar" msgid="4642708685386136807">"แถบนำทาง"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"การจัดวาง"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"ประเภทปุ่มทางซ้ายเพิ่มเติม"</string>
@@ -1160,4 +1152,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"ตรวจสอบสิทธิ์"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"เข้าถึงอุปกรณ์"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"ใช้ลายนิ้วมือเพื่อเปิด"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index fe75e01..d94e7a6 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Camera"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Telepono"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Voice Assist"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"I-unlock"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Naka-lock ang device"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Naghihintay ng fingerprint"</string>
@@ -289,11 +291,9 @@
<string name="accessibility_quick_settings_hotspot_changed_off" msgid="7002061268910095176">"Na-off ang mobile hotspot."</string>
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2576895346762408840">"Na-on ang mobile hotspot."</string>
<string name="accessibility_casting_turned_off" msgid="1387906158563374962">"Itinigil ang pagka-cast sa screen."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Naka-pause ang work mode."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Naka-on ang work mode."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Naka-pause ang work mode."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Na-on ang work mode."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Na-off ang Data Saver."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Na-on ang Data Saver."</string>
@@ -412,8 +412,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"<xliff:g id="DATA_LIMIT">%s</xliff:g> ang limitasyon"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"Babala sa <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"Profile sa trabaho"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"Naka-pause"</string>
<string name="quick_settings_night_display_label" msgid="8180030659141778180">"Night Light"</string>
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Mao-on sa sunset"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"Hanggang sunrise"</string>
@@ -473,14 +472,10 @@
<string name="interruption_level_none_twoline" msgid="8579382742855486372">"Ganap na\nkatahimikan"</string>
<string name="interruption_level_priority_twoline" msgid="8523482736582498083">"Priyoridad\nlang"</string>
<string name="interruption_level_alarms_twoline" msgid="2045067991335708767">"Mga alarm\nlang"</string>
- <!-- no translation found for keyguard_indication_charging_time_wireless (577856646141738675) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time (6492711711891071502) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_fast (8390311020603859480) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_slowly (301936949731705417) -->
- <skip />
+ <string name="keyguard_indication_charging_time_wireless" msgid="577856646141738675">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Wireless na nagcha-charge • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> na lang para mapuno"</string>
+ <string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Nagcha-charge • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> na lang para mapuno"</string>
+ <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mabilis na nagcha-charge • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> na lang para mapuno"</string>
+ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mabagal na nagcha-charge • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> na lang para mapuno"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Magpalit ng user"</string>
<string name="accessibility_multi_user_switch_switcher_with_current" msgid="5759855008166759399">"Magpalit ng user, kasalukuyang user <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_inactive" msgid="383168614528618402">"Kasalukuyang user <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -676,12 +671,10 @@
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</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>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Hindi naka-set up"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"I-unlock para magamit"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Nagkaproblema sa pagkuha ng iyong mga card, pakisubukan ulit sa ibang pagkakataon"</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Mga setting ng lock screen"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Profile sa trabaho"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Airplane mode"</string>
<string name="add_tile" msgid="6239678623873086686">"Magdagdag ng tile"</string>
@@ -871,8 +864,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"I-on"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"I-off"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"Hindi available"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"Naka-disable"</string>
<string name="nav_bar" msgid="4642708685386136807">"Navigation bar"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"Layout"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"Uri ng extra na button ng kaliwa"</string>
@@ -1160,4 +1152,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"i-authenticate"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"ilagay ang device"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Gamitin ang fingerprint para buksan"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 6d3743f..d5185fb 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -136,6 +136,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Kamera"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Telefon"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Sesli Yardım"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"Cüzdan"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"Kilidi aç"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Cihaz kilitlendi"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Parmak izi bekleniyor"</string>
@@ -289,11 +290,9 @@
<string name="accessibility_quick_settings_hotspot_changed_off" msgid="7002061268910095176">"Mobil hotspot kapatıldı."</string>
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2576895346762408840">"Mobil hotspot açıldı."</string>
<string name="accessibility_casting_turned_off" msgid="1387906158563374962">"Ekran yayını durduruldu."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Çalışma modu duraklatıldı."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Çalışma modu açık."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Çalışma modu duraklatıldı."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Çalışma modu açıldı."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Veri Tasarrufu kapatıldı."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Veri Tasarrufu açıldı."</string>
@@ -412,8 +411,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"Sınır: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"<xliff:g id="DATA_LIMIT">%s</xliff:g> uyarısı"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"İş profili"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"Duraklatıldı"</string>
<string name="quick_settings_night_display_label" msgid="8180030659141778180">"Gece Işığı"</string>
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Gün batımı açılacak"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"Sabaha kadar"</string>
@@ -473,14 +471,10 @@
<string name="interruption_level_none_twoline" msgid="8579382742855486372">"Tamamen\nsessiz"</string>
<string name="interruption_level_priority_twoline" msgid="8523482736582498083">"Yalnızca\nöncelik"</string>
<string name="interruption_level_alarms_twoline" msgid="2045067991335708767">"Yalnızca\nalarmlar"</string>
- <!-- no translation found for keyguard_indication_charging_time_wireless (577856646141738675) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time (6492711711891071502) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_fast (8390311020603859480) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_slowly (301936949731705417) -->
- <skip />
+ <string name="keyguard_indication_charging_time_wireless" msgid="577856646141738675">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Kablosuz şarj oluyor • Dolmasına <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> kaldı"</string>
+ <string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Şarj oluyor • Dolmasına <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> kaldı"</string>
+ <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Hızlı şarj oluyor • Dolmasına <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> kaldı"</string>
+ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Yavaş şarj oluyor • Dolmasına <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> kaldı"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Kullanıcı değiştirme"</string>
<string name="accessibility_multi_user_switch_switcher_with_current" msgid="5759855008166759399">"Kullanıcı değiştir. Geçerli kullanıcı: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_inactive" msgid="383168614528618402">"Geçerli kullanıcı: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -676,12 +670,10 @@
<string name="wallet_title" msgid="5369767670735827105">"Cüzdan"</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>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Ayarlanmadı"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Kullanmak için kilidi aç"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Kartlarınız alınırken bir sorun oluştu. Lütfen daha sonra tekrar deneyin"</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <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>
@@ -871,8 +863,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"Açık"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"Kapalı"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"Kullanılamıyor"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"Devre dışı bırakıldı"</string>
<string name="nav_bar" msgid="4642708685386136807">"Gezinme çubuğu"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"Düzen"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"Ekstra sol düğme türü"</string>
@@ -1129,7 +1120,7 @@
<string name="okay" msgid="6490552955618608554">"Tamam"</string>
<string name="timestamp" msgid="6577851592534538533">"<xliff:g id="DURATION">%1$s</xliff:g> önce"</string>
<string name="less_than_timestamp" msgid="6598972791137724517">"Henüz <xliff:g id="DURATION">%1$s</xliff:g> olmadı"</string>
- <string name="over_timestamp" msgid="4765793502859358634">"<xliff:g id="DURATION">%1$s</xliff:g> üzerinde bir süre önce"</string>
+ <string name="over_timestamp" msgid="4765793502859358634">"En az <xliff:g id="DURATION">%1$s</xliff:g> önce"</string>
<string name="birthday_status" msgid="2596961629465396761">"Doğum günü"</string>
<string name="birthday_status_content_description" msgid="682836371128282925">"Bugün <xliff:g id="NAME">%1$s</xliff:g> adlı kişinin doğum günü"</string>
<string name="upcoming_birthday_status" msgid="2005452239256870351">"Yaklaşan doğum günü"</string>
@@ -1160,4 +1151,6 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"kimlik doğrulaması yapın"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"cihaz girin"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Açmak için parmak izi kullanın"</string>
+ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Kimlik doğrulaması gerekiyor. Kimlik doğrulaması için parmak izi sensörüne dokunun."</string>
+ <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Devam eden telefon görüşmesi"</string>
</resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index c0f6e74..df9c5bf 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Камера"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Номер телефону"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Голосові підказки"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"Розблокувати"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Пристрій заблоковано"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Очікується відбиток пальця"</string>
@@ -289,11 +291,9 @@
<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_casting_turned_off" msgid="1387906158563374962">"Трансляцію екрана зупинено."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Робочий режим призупинено."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Робочий режим увімкнено."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Робочий режим призупинено."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Робочий режим увімкнено."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Заощадження трафіку вимкнено."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Заощадження трафіку ввімкнено."</string>
@@ -416,8 +416,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"Обмеження: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"Застереження: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"Робочий профіль"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"Призупинено"</string>
<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>
@@ -477,14 +476,10 @@
<string name="interruption_level_none_twoline" msgid="8579382742855486372">"Без\nсигналів"</string>
<string name="interruption_level_priority_twoline" msgid="8523482736582498083">"Лише\nприорітетні"</string>
<string name="interruption_level_alarms_twoline" msgid="2045067991335708767">"Лише\nсигнали"</string>
- <!-- no translation found for keyguard_indication_charging_time_wireless (577856646141738675) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time (6492711711891071502) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_fast (8390311020603859480) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_slowly (301936949731705417) -->
- <skip />
+ <string name="keyguard_indication_charging_time_wireless" msgid="577856646141738675">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Бездротове заряджання • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до повного заряду"</string>
+ <string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Заряджання • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до повного заряду"</string>
+ <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Швидке заряджання • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до повного заряду"</string>
+ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Повільне заряджання • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до повного заряду"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Змінити користувача"</string>
<string name="accessibility_multi_user_switch_switcher_with_current" msgid="5759855008166759399">"Змінити користувача, поточний користувач – <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_inactive" msgid="383168614528618402">"Поточний користувач: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -682,12 +677,10 @@
<string name="wallet_title" msgid="5369767670735827105">"Гаманець"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Показати все"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Розблокувати, щоб сплатити"</string>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Не налаштовано"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Розблокувати, щоб використовувати"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Не вдалось отримати ваші картки. Повторіть спробу пізніше."</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Параметри блокування екрана"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Робочий профіль"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Режим польоту"</string>
<string name="add_tile" msgid="6239678623873086686">"Додавання опції"</string>
@@ -881,8 +874,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"Увімкнено"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"Вимкнено"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"Недоступно"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"Вимкнено"</string>
<string name="nav_bar" msgid="4642708685386136807">"Панель навігації"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"Макет"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"Додатковий тип кнопки ліворуч"</string>
@@ -1172,4 +1164,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"пройти автентифікацію"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"відкрити пристрій"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Щоб відкрити, використайте відбиток пальця"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 491454a..be8fafb 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"کیمرا"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"فون"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"صوتی معاون"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"غیر مقفل کریں"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"آلہ مقفل کر دیا گیا"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"فنگر پرنٹ کا انتظار ہے"</string>
@@ -289,10 +291,9 @@
<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_casting_turned_off" msgid="1387906158563374962">"اسکرین کو کاسٹ کرنا بند کر دیا۔"</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"ورک موڈ موقوف ہے۔"</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"کام موڈ آن ہے۔"</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
+ <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (6422896967647049692) -->
<skip />
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"کام موڈ آن ہو گیا۔"</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"ڈیٹا سیور آف ہو گیا۔"</string>
@@ -412,8 +413,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"<xliff:g id="DATA_LIMIT">%s</xliff:g> حد"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"<xliff:g id="DATA_LIMIT">%s</xliff:g> وارننگ"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"دفتری پروفائل"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"موقوف ہے"</string>
<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>
@@ -473,14 +473,10 @@
<string name="interruption_level_none_twoline" msgid="8579382742855486372">"مکمل\nخاموشی"</string>
<string name="interruption_level_priority_twoline" msgid="8523482736582498083">"صرف\nترجیحی"</string>
<string name="interruption_level_alarms_twoline" msgid="2045067991335708767">"صرف\nالارمز"</string>
- <!-- no translation found for keyguard_indication_charging_time_wireless (577856646141738675) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time (6492711711891071502) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_fast (8390311020603859480) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_slowly (301936949731705417) -->
- <skip />
+ <string name="keyguard_indication_charging_time_wireless" msgid="577856646141738675">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • وائرلیس طریقے سے چارج ہو رہا ہے • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> میں مکمل"</string>
+ <string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • چارج ہو رہا ہے • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> میں مکمل"</string>
+ <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • تیزی سے چارج ہو رہا ہے • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> میں مکمل"</string>
+ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • آہستہ چارج ہو رہا ہے • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> میں مکمل"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"صارف سوئچ کریں"</string>
<string name="accessibility_multi_user_switch_switcher_with_current" msgid="5759855008166759399">"صارف سوئچ کریں، موجودہ صارف <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_inactive" msgid="383168614528618402">"موجودہ صارف <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -676,12 +672,10 @@
<string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"سبھی دکھائیں"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"ادائیگی کرنے کے لیے غیر مقفل کریں"</string>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"سیٹ اپ نہیں کیا گیا"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"استعمال کرنے کے لیے غیر مقفل کریں"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"آپ کے کارڈز حاصل کرنے میں ایک مسئلہ درپیش تھا، براہ کرم بعد میں دوبارہ کوشش کریں"</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"مقفل اسکرین کی ترتیبات"</string>
<string name="status_bar_work" msgid="5238641949837091056">"دفتری پروفائل"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"ہوائی جہاز وضع"</string>
<string name="add_tile" msgid="6239678623873086686">"ٹائل شامل کریں"</string>
@@ -871,8 +865,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"آن"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"آف"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"غیر دستیاب ہے"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"غیر فعال ہے"</string>
<string name="nav_bar" msgid="4642708685386136807">"نیویگیشن بار"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"لے آؤٹ"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"بائيں جانب کی اضافی بٹن کی قسم"</string>
@@ -1160,4 +1153,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"تصدیق کریں"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"آلہ درج کریں"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"کھولنے کے لیے فنگر پرنٹ کا استعمال کریں"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 1ba1eed..131373c 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -136,6 +136,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Kamera"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Telefon"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Ovozli yordam"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"Qulfdan chiqarish"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Qurilma qulflandi"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Barmoq izingizni skanerlang"</string>
@@ -291,7 +292,7 @@
<string name="accessibility_casting_turned_off" msgid="1387906158563374962">"Ekranni translatsiya qilish to‘xtadi."</string>
<string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Ish rejimi pauzada."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Ish rejimi yoniq."</string>
- <string name="accessibility_quick_settings_work_mode_changed_off" msgid="2653550342355027441">"Ish rejimi pauza qilindi."</string>
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Ish rejimi pauzada."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Ishchi rejim yoqildi."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Trafik tejash rejimi o‘chirib qo‘yildi."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Trafik tejash rejimi yoqildi."</string>
@@ -1150,4 +1151,6 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"autentifikatsiya"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"qurilmani ochish"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Ochish uchun barmoq izidan foydalaning"</string>
+ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Haqiqiylikni tekshirish talab etiladi. Autentifikatsiya uchun barmoq izi skaneriga tegining."</string>
+ <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Joriy telefon chaqiruvi"</string>
</resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 902c30f..7a381c5 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Máy ảnh"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Điện thoại"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Trợ lý thoại"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"Mở khóa"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Đã khóa thiết bị"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Đang chờ vân tay"</string>
@@ -289,11 +291,9 @@
<string name="accessibility_quick_settings_hotspot_changed_off" msgid="7002061268910095176">"Đã tắt điểm phát sóng di động."</string>
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2576895346762408840">"Đã bật điểm phát sóng di động."</string>
<string name="accessibility_casting_turned_off" msgid="1387906158563374962">"Đã ngừng truyền màn hình."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Đã tạm dừng chế độ công việc."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Chế độ làm việc bật."</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Đã tạm dừng chế độ công việc."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Chế độ làm việc đã bật."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Đã tắt Trình tiết kiệm dữ liệu."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Đã bật Trình tiết kiệm dữ liệu."</string>
@@ -412,8 +412,7 @@
<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="2754212289804324685">"Hồ sơ công việc"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"Đã tạm dừng"</string>
<string name="quick_settings_night_display_label" msgid="8180030659141778180">"Ánh sáng đêm"</string>
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Bật khi trời tối"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"Cho đến khi trời sáng"</string>
@@ -473,14 +472,10 @@
<string name="interruption_level_none_twoline" msgid="8579382742855486372">"Hoàn toàn\ntắt tiếng"</string>
<string name="interruption_level_priority_twoline" msgid="8523482736582498083">"Chỉ\nưu tiên"</string>
<string name="interruption_level_alarms_twoline" msgid="2045067991335708767">"Chỉ\nbáo thức"</string>
- <!-- no translation found for keyguard_indication_charging_time_wireless (577856646141738675) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time (6492711711891071502) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_fast (8390311020603859480) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_slowly (301936949731705417) -->
- <skip />
+ <string name="keyguard_indication_charging_time_wireless" msgid="577856646141738675">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Đang sạc không dây • Sẽ đầy sau <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Đang sạc • Sẽ đầy sau <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Đang sạc nhanh • Sẽ đầy sau <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Đang sạc chậm • Sẽ đầy sau <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Chuyển đổi người dùng"</string>
<string name="accessibility_multi_user_switch_switcher_with_current" msgid="5759855008166759399">"Chuyển người dùng, người dùng hiện tại <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_inactive" msgid="383168614528618402">"Người dùng hiện tại <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -676,12 +671,10 @@
<string name="wallet_title" msgid="5369767670735827105">"Ví"</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>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"Chưa thiết lập"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Mở khóa để sử dụng"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Đã xảy ra sự cố khi tải thẻ của bạn. Vui lòng thử lại sau"</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Cài đặt màn hình khóa"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Hồ sơ công việc"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Chế độ máy bay"</string>
<string name="add_tile" msgid="6239678623873086686">"Thêm ô"</string>
@@ -871,8 +864,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"Đang bật"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"Đang tắt"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"Không có sẵn"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"Đã tắt"</string>
<string name="nav_bar" msgid="4642708685386136807">"Thanh điều hướng"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"Bố cục"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"Loại nút bổ sung bên trái"</string>
@@ -1144,7 +1136,7 @@
<string name="audio_status" msgid="4237055636967709208">"Đang nghe"</string>
<string name="game_status" msgid="1340694320630973259">"Đang chơi"</string>
<string name="empty_user_name" msgid="3389155775773578300">"Bạn bè"</string>
- <string name="empty_status" msgid="5938893404951307749">"Cùng trò chuyện tối nay nhé!"</string>
+ <string name="empty_status" msgid="5938893404951307749">"Tối nay nói chuyện nhé!"</string>
<string name="status_before_loading" msgid="1500477307859631381">"Nội dung sẽ sớm hiển thị"</string>
<string name="missed_call" msgid="4228016077700161689">"Cuộc gọi nhỡ"</string>
<string name="messages_count_overflow_indicator" msgid="7850934067082006043">"Hơn <xliff:g id="NUMBER">%d</xliff:g>"</string>
@@ -1160,4 +1152,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"xác thực"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"truy cập thiết bị"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Dùng vân tay để mở"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 728e025..0f162be 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"相机"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"电话"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"语音助理"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"解锁"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"设备已锁定"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"正在等待提供指纹"</string>
@@ -289,11 +291,9 @@
<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_casting_turned_off" msgid="1387906158563374962">"屏幕投射已停止。"</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"工作模式已暂停。"</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"工作模式开启。"</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"工作模式已暂停。"</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"工作模式已开启。"</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"流量节省程序已关闭。"</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"流量节省程序已开启。"</string>
@@ -412,8 +412,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"上限为<xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"<xliff:g id="DATA_LIMIT">%s</xliff:g>警告"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"工作资料"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"已暂停"</string>
<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>
@@ -473,14 +472,10 @@
<string name="interruption_level_none_twoline" msgid="8579382742855486372">"完全\n静音"</string>
<string name="interruption_level_priority_twoline" msgid="8523482736582498083">"仅限\n优先打扰"</string>
<string name="interruption_level_alarms_twoline" msgid="2045067991335708767">"仅限\n闹钟"</string>
- <!-- no translation found for keyguard_indication_charging_time_wireless (577856646141738675) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time (6492711711891071502) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_fast (8390311020603859480) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_slowly (301936949731705417) -->
- <skip />
+ <string name="keyguard_indication_charging_time_wireless" msgid="577856646141738675">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 正在无线充电 • 将于 <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>后充满"</string>
+ <string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 正在充电 • 将于 <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>后充满"</string>
+ <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 正在快速充电 • 将于 <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>后充满"</string>
+ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 正在慢速充电 • 将于 <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>后充满"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"切换用户"</string>
<string name="accessibility_multi_user_switch_switcher_with_current" msgid="5759855008166759399">"切换用户,当前用户为<xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_inactive" msgid="383168614528618402">"当前用户为<xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -676,12 +671,10 @@
<string name="wallet_title" msgid="5369767670735827105">"电子钱包"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"全部显示"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"解锁设备才能付款"</string>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"未设置"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"解锁设备即可使用"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"获取您的卡片时出现问题,请稍后重试"</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"锁定屏幕设置"</string>
<string name="status_bar_work" msgid="5238641949837091056">"工作资料"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"飞行模式"</string>
<string name="add_tile" msgid="6239678623873086686">"添加图块"</string>
@@ -871,8 +864,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"开启"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"关闭"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"不可用"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"已停用"</string>
<string name="nav_bar" msgid="4642708685386136807">"导航栏"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"布局"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"其他向左按钮类型"</string>
@@ -1148,7 +1140,7 @@
<string name="status_before_loading" msgid="1500477307859631381">"内容很快就会显示,请稍候"</string>
<string name="missed_call" msgid="4228016077700161689">"未接电话"</string>
<string name="messages_count_overflow_indicator" msgid="7850934067082006043">"<xliff:g id="NUMBER">%d</xliff:g>+"</string>
- <string name="people_tile_description" msgid="8154966188085545556">"查看最近的信息、未接电话和状态更新"</string>
+ <string name="people_tile_description" msgid="8154966188085545556">"查看近期的消息、未接电话和状态更新"</string>
<string name="people_tile_title" msgid="6589377493334871272">"对话"</string>
<string name="new_notification_text_content_description" msgid="5574393603145263727">"<xliff:g id="NAME">%1$s</xliff:g>发送了一条消息"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g>发送了一张图片"</string>
@@ -1160,4 +1152,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"身份验证"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"进入设备"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"使用指纹即可打开"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 165ccf9..cd02e78 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"相機"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"電話"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"語音助手"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"解鎖"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"裝置已上鎖"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"正在等待指紋"</string>
@@ -289,11 +291,9 @@
<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_casting_turned_off" msgid="1387906158563374962">"已停止投放螢幕。"</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"工作模式已暫停。"</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"工作模式已開啟。"</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"工作模式已暫停。"</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"已開啟工作模式。"</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"已關閉數據節省模式。"</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"已開啟數據節省模式。"</string>
@@ -412,8 +412,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"上限為 <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"<xliff:g id="DATA_LIMIT">%s</xliff:g> 警告"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"工作設定檔"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"已暫停"</string>
<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>
@@ -473,14 +472,10 @@
<string name="interruption_level_none_twoline" msgid="8579382742855486372">"完全\n靜音"</string>
<string name="interruption_level_priority_twoline" msgid="8523482736582498083">"僅限\n優先"</string>
<string name="interruption_level_alarms_twoline" msgid="2045067991335708767">"僅限\n鬧鐘"</string>
- <!-- no translation found for keyguard_indication_charging_time_wireless (577856646141738675) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time (6492711711891071502) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_fast (8390311020603859480) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_slowly (301936949731705417) -->
- <skip />
+ <string name="keyguard_indication_charging_time_wireless" msgid="577856646141738675">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 無線充電中 • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>後充滿電"</string>
+ <string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 充電中 • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>後充滿電"</string>
+ <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 快速充電中 • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>後充滿電"</string>
+ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 慢速充電中 • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>後充滿電"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"切換使用者"</string>
<string name="accessibility_multi_user_switch_switcher_with_current" msgid="5759855008166759399">"切換使用者,目前使用者是<xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_inactive" msgid="383168614528618402">"目前的使用者是 <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -676,12 +671,10 @@
<string name="wallet_title" msgid="5369767670735827105">"電子錢包"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"顯示全部"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"解鎖裝置才能付款"</string>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"未設定"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"解鎖即可使用"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"擷取資訊卡時發生問題,請稍後再試。"</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"上鎖畫面設定"</string>
<string name="status_bar_work" msgid="5238641949837091056">"工作設定檔"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"飛行模式"</string>
<string name="add_tile" msgid="6239678623873086686">"加入圖塊"</string>
@@ -871,8 +864,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"開啟"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"關閉"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"無法使用"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"已停用"</string>
<string name="nav_bar" msgid="4642708685386136807">"導覽列"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"配置"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"其他向左按鈕類型"</string>
@@ -1123,7 +1115,7 @@
<string name="basic_status" msgid="2315371112182658176">"開啟對話"</string>
<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="no_conversations_text" msgid="7362374212649891057">"等你收到一些訊息後再回來查看吧"</string>
<string name="priority_conversations" msgid="3967482288896653039">"優先對話"</string>
<string name="recent_conversations" msgid="8531874684782574622">"最近的對話"</string>
<string name="okay" msgid="6490552955618608554">"確定"</string>
@@ -1144,7 +1136,7 @@
<string name="audio_status" msgid="4237055636967709208">"正在聽取音訊"</string>
<string name="game_status" msgid="1340694320630973259">"正在玩遊戲"</string>
<string name="empty_user_name" msgid="3389155775773578300">"朋友"</string>
- <string name="empty_status" msgid="5938893404951307749">"今晚聊天吧!"</string>
+ <string name="empty_status" msgid="5938893404951307749">"今晚傾下偈啦!"</string>
<string name="status_before_loading" msgid="1500477307859631381">"即將顯示內容"</string>
<string name="missed_call" msgid="4228016077700161689">"未接來電"</string>
<string name="messages_count_overflow_indicator" msgid="7850934067082006043">"<xliff:g id="NUMBER">%d</xliff:g>+"</string>
@@ -1160,4 +1152,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"驗證"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"進入裝置"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"使用指紋即可開啟"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 8e2ecda..043cf43 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -136,6 +136,8 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"相機"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"電話"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"語音小幫手"</string>
+ <!-- no translation found for accessibility_wallet_button (1458258783460555507) -->
+ <skip />
<string name="accessibility_unlock_button" msgid="122785427241471085">"解除鎖定"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"裝置已鎖定"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"正在等候指紋"</string>
@@ -289,11 +291,9 @@
<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_casting_turned_off" msgid="1387906158563374962">"已停止投放螢幕。"</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_off (9106217884005620744) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"工作模式已暫停。"</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"工作模式已開啟。"</string>
- <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (2653550342355027441) -->
- <skip />
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"工作模式已暫停。"</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"工作模式已開啟。"</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"數據節省模式已關閉。"</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"數據節省模式已開啟。"</string>
@@ -412,8 +412,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"上限為 <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"<xliff:g id="DATA_LIMIT">%s</xliff:g> 警告"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"工作資料夾"</string>
- <!-- no translation found for quick_settings_work_mode_paused (4841109346916998613) -->
- <skip />
+ <string name="quick_settings_work_mode_paused" msgid="4841109346916998613">"已暫停"</string>
<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>
@@ -473,14 +472,10 @@
<string name="interruption_level_none_twoline" msgid="8579382742855486372">"完全\n靜音"</string>
<string name="interruption_level_priority_twoline" msgid="8523482736582498083">"僅允許\n優先通知"</string>
<string name="interruption_level_alarms_twoline" msgid="2045067991335708767">"僅允許\n鬧鐘"</string>
- <!-- no translation found for keyguard_indication_charging_time_wireless (577856646141738675) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time (6492711711891071502) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_fast (8390311020603859480) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_slowly (301936949731705417) -->
- <skip />
+ <string name="keyguard_indication_charging_time_wireless" msgid="577856646141738675">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 無線充電中 • 將於 <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>後充飽"</string>
+ <string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 充電中 • 將於 <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>後充飽"</string>
+ <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 快速充電中 • 將於 <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>後充飽"</string>
+ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 慢速充電中 • 將於 <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>後充飽"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"切換使用者"</string>
<string name="accessibility_multi_user_switch_switcher_with_current" msgid="5759855008166759399">"切換使用者,目前使用者是<xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_inactive" msgid="383168614528618402">"目前使用者是「<xliff:g id="CURRENT_USER_NAME">%s</xliff:g>」"</string>
@@ -676,12 +671,10 @@
<string name="wallet_title" msgid="5369767670735827105">"電子錢包"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"顯示全部"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"解鎖裝置才能付款"</string>
- <!-- no translation found for wallet_secondary_label_no_card (1282609666895946317) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="1282609666895946317">"未設定"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"解鎖即可使用"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"擷取卡片時發生問題,請稍後再試"</string>
- <!-- no translation found for wallet_lockscreen_settings_label (3539105300870383570) -->
- <skip />
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"螢幕鎖定設定"</string>
<string name="status_bar_work" msgid="5238641949837091056">"工作資料夾"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"飛航模式"</string>
<string name="add_tile" msgid="6239678623873086686">"新增圖塊"</string>
@@ -871,8 +864,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"開啟"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"關閉"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"無法使用"</string>
- <!-- no translation found for tile_disabled (373212051546573069) -->
- <skip />
+ <string name="tile_disabled" msgid="373212051546573069">"已停用"</string>
<string name="nav_bar" msgid="4642708685386136807">"導覽列"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"配置"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"其他向左按鈕類型"</string>
@@ -1160,4 +1152,8 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"驗證"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"進入裝置"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"使用指紋即可開啟"</string>
+ <!-- no translation found for accessibility_fingerprint_bouncer (7189102492498735519) -->
+ <skip />
+ <!-- no translation found for ongoing_phone_call_content_description (5332334388483099947) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 0ec4a4b..a444cd0 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -136,6 +136,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Ikhamela"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Ifoni"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Isisekeli sezwi"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"I-wallet"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"Vula"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Idivayisi ikhiyiwe"</string>
<string name="accessibility_waiting_for_fingerprint" msgid="5209142744692162598">"Ilindele izigxivizo zeminwe"</string>
@@ -291,7 +292,7 @@
<string name="accessibility_casting_turned_off" msgid="1387906158563374962">"Ukusakaza kwesikrini kumisiwe."</string>
<string name="accessibility_quick_settings_work_mode_off" msgid="9106217884005620744">"Imodi yokusebenza imisiwe."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Imodi yomsebenzi ivuliwe."</string>
- <string name="accessibility_quick_settings_work_mode_changed_off" msgid="2653550342355027441">"Imodi yokusebenza imisiwe."</string>
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"Imodi yokusebenza imisiwe."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Imodi yomsebenzi ivuliwe."</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Iseva yedatha ivaliwe."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Iseva yedatha ivuliwe."</string>
@@ -470,14 +471,10 @@
<string name="interruption_level_none_twoline" msgid="8579382742855486372">"Ukuthula\niokuphelele"</string>
<string name="interruption_level_priority_twoline" msgid="8523482736582498083">"Okubalulekile\nkuphela"</string>
<string name="interruption_level_alarms_twoline" msgid="2045067991335708767">"Ama-alamu\nkuphela"</string>
- <!-- no translation found for keyguard_indication_charging_time_wireless (577856646141738675) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time (6492711711891071502) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_fast (8390311020603859480) -->
- <skip />
- <!-- no translation found for keyguard_indication_charging_time_slowly (301936949731705417) -->
- <skip />
+ <string name="keyguard_indication_charging_time_wireless" msgid="577856646141738675">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ishajwa ngokungaxhunyiwe • Izogcwala ngo-<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Iyashaja • Izogcwala ngo-<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ishaja ngokushesha • Izogcwala ngo-<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ishaja kancane • Izogcwala ngo-<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Shintsha umsebenzisi"</string>
<string name="accessibility_multi_user_switch_switcher_with_current" msgid="5759855008166759399">"Shintsha umsebenzisi, umsebenzisi wamanje ngu-<xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_inactive" msgid="383168614528618402">"Umsebenzisi wamanje <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -1154,4 +1151,6 @@
<string name="accessibility_authenticate_hint" msgid="798914151813205721">"gunyaza"</string>
<string name="accessibility_enter_hint" msgid="2617864063504824834">"faka idivayisi"</string>
<string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Sebenzisa izigxivizo zeminwe ukuvula"</string>
+ <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Ukufakazela ubuqiniso budingekile. Thinta inzwa yezigxivizo zeminwe ukuze uqinisekise."</string>
+ <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Ikholi yefoni eqhubekayo"</string>
</resources>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 7101935..5559600 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -35,7 +35,6 @@
<color name="status_bar_clock_color">#FFFFFFFF</color>
<color name="qs_user_detail_icon_muted">#FFFFFFFF</color> <!-- not so muted after all -->
<color name="qs_tile_disabled_color">#9E9E9E</color> <!-- 38% black -->
- <color name="qs_footer_action_border">#2E312C</color>
<!-- The color of the background in the separated list of the Global Actions menu -->
<color name="global_actions_separated_background">#F5F5F5</color>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 87a669f..b292d7e 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1293,7 +1293,7 @@
<dimen name="magnification_drag_view_size">36dp</dimen>
<dimen name="magnification_controls_size">90dp</dimen>
<dimen name="magnification_switch_button_size">48dp</dimen>
- <dimen name="magnification_switch_button_padding">6dp</dimen>
+ <dimen name="magnification_switch_button_margin">16dp</dimen>
<dimen name="magnifier_left_right_controls_width">35dp</dimen>
<dimen name="magnifier_left_right_controls_height">45dp</dimen>
<dimen name="magnifier_up_down_controls_width">45dp</dimen>
@@ -1409,23 +1409,53 @@
<dimen name="media_output_dialog_icon_corner_radius">16dp</dimen>
<dimen name="media_output_dialog_title_anim_y_delta">12.5dp</dimen>
+ <!-- Delay after which the media will start transitioning to the full shade on
+ the lockscreen -->
+ <dimen name="lockscreen_shade_media_transition_start_delay">40dp</dimen>
+
+ <!-- Distance that the full shade transition takes in order for qs to fully transition to the
+ shade -->
+ <dimen name="lockscreen_shade_qs_transition_distance">200dp</dimen>
+
+ <!-- Distance that the full shade transition takes in order for scrim to fully transition to
+ the shade (in alpha) -->
+ <dimen name="lockscreen_shade_scrim_transition_distance">80dp</dimen>
+
+ <!-- Extra inset for the notifications when accounting for media during the lockscreen to
+ shade transition to compensate for the disappearing media -->
+ <dimen name="lockscreen_shade_transition_extra_media_inset">-48dp</dimen>
+
+ <!-- Maximum overshoot for the topPadding of notifications when transitioning to the full
+ shade -->
+ <dimen name="lockscreen_shade_max_top_overshoot">32dp</dimen>
+
<dimen name="people_space_widget_radius">28dp</dimen>
<dimen name="people_space_image_radius">20dp</dimen>
<dimen name="people_space_messages_count_radius">12dp</dimen>
<dimen name="people_space_widget_background_padding">6dp</dimen>
- <dimen name="required_width_for_medium">146dp</dimen>
+ <dimen name="required_width_for_medium">136dp</dimen>
<dimen name="required_width_for_large">138dp</dimen>
- <dimen name="required_height_for_large">182dp</dimen>
+ <dimen name="required_height_for_large">168dp</dimen>
<dimen name="default_width">146dp</dimen>
<dimen name="default_height">92dp</dimen>
<dimen name="avatar_size_for_medium">52dp</dimen>
<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_medium">14sp</dimen>
- <dimen name="name_text_size_for_large">24sp</dimen>
+ <dimen name="name_text_size_for_content">12sp</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>
+ <dimen name="name_text_size_for_large">16sp</dimen>
<dimen name="content_text_size_for_medium">12sp</dimen>
<dimen name="content_text_size_for_large">14sp</dimen>
+ <dimen name="below_name_text_padding">16dp</dimen>
+ <dimen name="above_notification_text_padding">22dp</dimen>
+ <dimen name="regular_predefined_icon">18dp</dimen>
+ <dimen name="large_predefined_icon">24dp</dimen>
+ <dimen name="availability_dot_status_padding">8dp</dimen>
+ <dimen name="availability_dot_notification_padding">12dp</dimen>
+ <dimen name="medium_content_padding_above_name">4dp</dimen>
<!-- Accessibility floating menu -->
<dimen name="accessibility_floating_menu_elevation">5dp</dimen>
diff --git a/packages/SystemUI/res/values/flags.xml b/packages/SystemUI/res/values/flags.xml
index 6104588..6393147 100644
--- a/packages/SystemUI/res/values/flags.xml
+++ b/packages/SystemUI/res/values/flags.xml
@@ -49,4 +49,6 @@
<bool name="flag_ongoing_call_status_bar_chip">true</bool>
<bool name="flag_smartspace">false</bool>
+
+ <bool name="flag_smartspace_deduping">true</bool>
</resources>
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index bb9d331..bdc7bdb 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -157,9 +157,6 @@
<item type="id" name="accessibility_action_qs_move_to_position" />
<item type="id" name="accessibility_action_qs_add_to_position" />
- <!-- Accessibility actions for PIP -->
- <item type="id" name="action_pip_resize" />
-
<!-- Accessibility actions for window magnification. -->
<item type="id" name="accessibility_action_zoom_in"/>
<item type="id" name="accessibility_action_zoom_out"/>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 427ede5..71382f3 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -691,10 +691,6 @@
<string name="accessibility_quick_settings_hotspot_changed_on">Mobile hotspot turned on.</string>
<!-- Announcement made when the screen stopped casting (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_casting_turned_off">Screen casting stopped.</string>
- <!-- Content description of the work mode title in quick settings when off (not shown on the screen). Paused is used as an adjective [CHAR LIMIT=NONE] -->
- <string name="accessibility_quick_settings_work_mode_off">Work mode paused.</string>
- <!-- Content description of the work mode title in quick settings when on (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_quick_settings_work_mode_on">Work mode on.</string>
<!-- Announcement made when the work mode changes to off (not shown on the screen). Paused is used as a verb. [CHAR LIMIT=NONE] -->
<string name="accessibility_quick_settings_work_mode_changed_off">Work mode paused.</string>
<!-- Announcement made when the work mode changes to on (not shown on the screen). [CHAR LIMIT=NONE] -->
@@ -953,11 +949,9 @@
<string name="quick_settings_cellular_detail_data_warning"><xliff:g id="data_limit" example="2.0 GB">%s</xliff:g> warning</string>
<!-- QuickSettings: This string is in the easy-to-view settings that a user can pull down from
the top of their phone's screen. This is a label for a toggle to turn the work profile on and
- off. "Work profile" means a separate profile on a user's phone that's specifically for their
+ off. This means a separate profile on a user's phone that's specifically for their
work apps and managed by their company. "Work" is used as an adjective. [CHAR LIMIT=NONE] -->
- <string name="quick_settings_work_mode_label">Work profile</string>
- <!-- QuickSettings: Secondary label for work mode tile when it's off. [CHAR LIMIT=NONE] -->
- <string name="quick_settings_work_mode_paused">Paused</string>
+ <string name="quick_settings_work_mode_label">Work apps</string>
<!-- QuickSettings: Label for the toggle to activate Night display (renamed "Night Light" with title caps). [CHAR LIMIT=20] -->
<string name="quick_settings_night_display_label">Night Light</string>
<!-- QuickSettings: Secondary text for when the Night Light will be enabled at sunset. [CHAR LIMIT=20] -->
@@ -2724,15 +2718,8 @@
<string name="accessibility_floating_button_action_double_tap_to_toggle">toggle</string>
<!-- Device Controls strings -->
- <!-- Device Controls empty state, title [CHAR LIMIT=30] -->
- <string name="quick_controls_title">Device controls</string>
- <!-- Device Controls empty state, subtitle [CHAR LIMIT=100] -->
- <string name="quick_controls_subtitle">Add controls for your connected devices</string>
-
- <!-- Device Controls setup, title [CHAR LIMIT=50] -->
- <string name="quick_controls_setup_title">Set up device controls</string>
- <!-- Device Controls setup, subtitle [CHAR LIMIT=100] -->
- <string name="quick_controls_setup_subtitle">Hold the Power button to access your controls</string>
+ <!-- Device Controls, Quick Settings tile title [CHAR LIMIT=30] -->
+ <string name="quick_controls_title">Home controls</string>
<!-- Controls management providers screen title [CHAR LIMIT=60]-->
<string name="controls_providers_title">Choose app to add controls</string>
@@ -2761,7 +2748,7 @@
<!-- Controls management controls screen default title [CHAR LIMIT=30] -->
<string name="controls_favorite_default_title">Controls</string>
<!-- Controls management controls screen subtitle [CHAR LIMIT=NONE] -->
- <string name="controls_favorite_subtitle">Choose controls to access from the power menu</string>
+ <string name="controls_favorite_subtitle">Choose controls to access from Quick Settings</string>
<!-- Controls management editing screen, user direction for rearranging controls [CHAR LIMIT=NONE] -->
<string name="controls_favorite_rearrange">Hold & drag to rearrange controls</string>
@@ -2853,7 +2840,7 @@
<!-- Stateless control message informing the user that a routine has started [CHAR_LIMIT=30] -->
<string name="controls_in_progress">In progress</string>
<!-- Tooltip informing user where the recently added controls are [CHAR_LIMIT=100] -->
- <string name="controls_added_tooltip">Hold Power button to see new controls</string>
+ <string name="controls_added_tooltip">Open Quick Settings to see new controls</string>
<!-- Controls menu, add [CHAR_LIMIT=30] -->
<string name="controls_menu_add">Add controls</string>
@@ -2894,12 +2881,16 @@
<string name="recent_conversations">Recent conversations</string>
<!-- Text for button dismissing configuration activity with no conversations [CHAR LIMIT=20] -->
<string name="okay">Okay</string>
- <!-- Timestamp for notification with exact time [CHAR LIMIT=25] -->
- <string name="timestamp"><xliff:g id="duration" example="5 hours">%1$s</xliff:g> ago</string>
- <!-- Timestamp for notification when less than a certain time window [CHAR LIMIT=25] -->
- <string name="less_than_timestamp">Less than <xliff:g id="duration" example="5 hours">%1$s</xliff:g> ago</string>
- <!-- Timestamp for notification when over a certain time window [CHAR LIMIT=25] -->
- <string name="over_timestamp">Over <xliff:g id="duration" example="1 week">%1$s</xliff:g> ago</string>
+ <!-- Timestamp for notification with exact time in days plural [CHAR LIMIT=25] -->
+ <string name="days_timestamp"><xliff:g id="duration" example="5">%1$s</xliff:g> days ago</string>
+ <!-- Timestamp for notification from one week ago[CHAR LIMIT=25] -->
+ <string name="one_week_timestamp">1 week ago</string>
+ <!-- Timestamp for notification from two weeks ago [CHAR LIMIT=25] -->
+ <string name="two_weeks_timestamp">2 weeks ago</string>
+ <!-- Timestamp for notification when over one week ago [CHAR LIMIT=25] -->
+ <string name="over_one_week_timestamp">Over 1 week ago</string>
+ <!-- Timestamp for notification when over two weeks ago [CHAR LIMIT=25] -->
+ <string name="over_two_weeks_timestamp">Over 2 weeks ago</string>
<!-- Status text on the Conversation widget for a birthday today [CHAR LIMIT=20] -->
<string name="birthday_status">Birthday</string>
<!-- Content description text on the Conversation widget for a birthday today [CHAR LIMIT=150] -->
@@ -2952,8 +2943,6 @@
[CHAR LIMIT=NONE] -->
<string name="battery_state_unknown_notification_text">Tap for more information</string>
- <string name="qs_tile_label_fontFamily" translatable="false">@*android:string/config_headlineFontFamilyMedium</string>
-
<!-- Secondary label for alarm tile when there is no next alarm information [CHAR LIMIT=20] -->
<string name="qs_alarm_tile_no_alarm">No alarm set</string>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 9fa63dd..9ce7589 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -197,12 +197,13 @@
<style name="TextAppearance.QS.TileLabel">
<item name="android:textSize">@dimen/qs_tile_text_size</item>
- <item name="android:fontFamily">@string/qs_tile_label_fontFamily</item>
+ <item name="android:letterSpacing">0.01</item>
+ <item name="android:lineHeight">20sp</item>
+ <item name="android:fontFamily">@*android:string/config_headlineFontFamilyMedium</item>
</style>
<style name="TextAppearance.QS.TileLabel.Secondary">
- <item name="android:textSize">@dimen/qs_tile_text_size</item>
- <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
+ <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
</style>
<style name="TextAppearance.QS.UserSwitcher">
@@ -221,11 +222,6 @@
<item name="android:textSize">@dimen/celltile_rat_type_size</item>
</style>
- <style name="TextAppearance.QS.SecurityFooter">
- <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
- <item name="android:textSize">@dimen/qs_tile_text_size</item>
- </style>
-
<style name="TextAppearance.QS.Status">
<item name="android:fontFamily">@*android:string/config_headlineFontFamilyMedium</item>
<item name="android:textColor">?android:attr/textColorPrimary</item>
@@ -234,14 +230,22 @@
<item name="android:lineHeight">20sp</item>
</style>
- <style name="TextAppearance.QS.Status.NoCarrierText">
- <item name="android:textColor">?android:attr/textColorTertiary</item>
- </style>
-
- <style name="TextAppearance.QS.Build">
+ <style name="TextAppearance.QS.SecurityFooter" parent="@style/TextAppearance.QS.Status">
<item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
<item name="android:textColor">?android:attr/textColorSecondary</item>
- <item name="android:textSize">14sp</item>
+ </style>
+
+ <style name="TextAppearance.QS.Status.Carriers">
+ <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
+ </style>
+
+ <style name="TextAppearance.QS.Status.Carriers.NoCarrierText">
+ <item name="android:textColor">?android:attr/textColorSecondary</item>
+ </style>
+
+ <style name="TextAppearance.QS.Status.Build">
+ <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
+ <item name="android:textColor">?android:attr/textColorSecondary</item>
</style>
<style name="TextAppearance.DeviceManagementDialog">
@@ -603,11 +607,12 @@
parent="@*android:style/TextAppearance.DeviceDefault.Notification.Info">
</style>
- <style name="TextAppearance.QSEdit.Headers"
- parent="@*android:style/TextAppearance.DeviceDefault.Body2">
- <item name="android:textSize">11sp</item>
+ <style name="TextAppearance.QSEdit" >
+ <item name="android:textSize">14sp</item>
+ <item name="android:letterSpacing">0.01</item>
+ <item name="android:lineHeight">20sp</item>
+ <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
<item name="android:textColor">?android:attr/textColorSecondary</item>
- <item name="android:textAllCaps">true</item>
</style>
<style name="QSCustomizeToolbar" parent="@*android:style/Widget.DeviceDefault.Toolbar">
@@ -649,19 +654,14 @@
</style>
<style name="MediaPlayer.SolidButton">
- <item name="android:backgroundTint">?android:attr/colorAccent</item>
+ <item name="android:backgroundTint">@color/media_player_solid_button_bg</item>
<item name="android:tint">?android:attr/colorPrimary</item>
- <item name="android:textColor">?android:attr/colorPrimary</item>
+ <item name="android:textColor">?android:attr/textColorPrimary</item>
</style>
<style name="MediaPlayer.AppIcon">
<item name="android:background">@drawable/qs_media_icon_background</item>
- <item name="android:backgroundTint">?android:attr/colorPrimary</item>
- <item name="android:tint">?android:attr/colorAccent</item>
- </style>
-
- <style name="MediaPlayer.AppIcon.Recommendation" parent="MediaPlayer.AppIcon">
- <item name="android:tint">@color/transparent</item>
+ <item name="android:backgroundTint">?android:attr/textColorPrimary</item>
</style>
<style name="MediaPlayer.Album">
diff --git a/packages/SystemUI/res/xml/media_collapsed.xml b/packages/SystemUI/res/xml/media_collapsed.xml
index bdb8c04..a03a1d3 100644
--- a/packages/SystemUI/res/xml/media_collapsed.xml
+++ b/packages/SystemUI/res/xml/media_collapsed.xml
@@ -69,6 +69,7 @@
android:layout_marginBottom="@dimen/qs_media_padding"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent"
/>
<!-- Song name -->
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInstanceManager.java b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInstanceManager.java
index 2b35bcd..c90833c 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInstanceManager.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInstanceManager.java
@@ -345,7 +345,7 @@
// Create our own ClassLoader so we can use our own code as the parent.
ClassLoader classLoader = mManager.getClassLoader(info);
Context pluginContext = new PluginContextWrapper(
- mContext.createApplicationContext(info, 0), classLoader);
+ mContext.createPackageContext(pkg, 0), classLoader);
Class<?> pluginClass = Class.forName(cls, true, classLoader);
// TODO: Only create the plugin before version check if we need it for
// legacy version check.
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
index 1e98f86..f61cadb 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
@@ -134,5 +134,8 @@
*/
void onBackPressed() = 44;
- // Next id = 45
+ /** Sets home rotation enabled. */
+ void setHomeRotationEnabled(boolean enabled) = 45;
+
+ // Next id = 46
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/InteractionJankMonitorWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/InteractionJankMonitorWrapper.java
index bec9220..d40b94c 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/InteractionJankMonitorWrapper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/InteractionJankMonitorWrapper.java
@@ -40,6 +40,8 @@
InteractionJankMonitor.CUJ_LAUNCHER_OPEN_ALL_APPS;
public static final int CUJ_ALL_APPS_SCROLL =
InteractionJankMonitor.CUJ_LAUNCHER_ALL_APPS_SCROLL;
+ public static final int CUJ_APP_LAUNCH_FROM_WIDGET =
+ InteractionJankMonitor.CUJ_LAUNCHER_APP_LAUNCH_FROM_WIDGET;
@IntDef({
CUJ_APP_LAUNCH_FROM_RECENTS,
@@ -47,6 +49,7 @@
CUJ_APP_CLOSE_TO_HOME,
CUJ_APP_CLOSE_TO_PIP,
CUJ_QUICK_SWITCH,
+ CUJ_APP_LAUNCH_FROM_WIDGET,
})
@Retention(RetentionPolicy.SOURCE)
public @interface CujType {
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
index 1cc488f..700ec49 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
@@ -19,6 +19,7 @@
import android.os.RemoteException;
import android.util.Log;
import android.view.IRecentsAnimationController;
+import android.view.SurfaceControl;
import android.window.PictureInPictureSurfaceTransaction;
import android.window.TaskSnapshot;
@@ -76,11 +77,13 @@
* updated accordingly. This should be called before `finish`
* @param taskId Task id of the Activity in PiP mode.
* @param finishTransaction leash operations for the final transform.
+ * @param overlay the surface control for an overlay being shown above the pip (can be null)
*/
public void setFinishTaskTransaction(int taskId,
- PictureInPictureSurfaceTransaction finishTransaction) {
+ PictureInPictureSurfaceTransaction finishTransaction,
+ SurfaceControl overlay) {
try {
- mAnimationController.setFinishTaskTransaction(taskId, finishTransaction);
+ mAnimationController.setFinishTaskTransaction(taskId, finishTransaction, overlay);
} catch (RemoteException e) {
Log.d(TAG, "Failed to set finish task bounds", e);
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationAdapterCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationAdapterCompat.java
index 22d934e..ee55bf0 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationAdapterCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationAdapterCompat.java
@@ -28,6 +28,7 @@
import android.annotation.SuppressLint;
import android.os.IBinder;
import android.os.RemoteException;
+import android.util.ArrayMap;
import android.util.Log;
import android.view.IRemoteAnimationFinishedCallback;
import android.view.IRemoteAnimationRunner;
@@ -158,10 +159,11 @@
public void startAnimation(IBinder token, TransitionInfo info,
SurfaceControl.Transaction t,
IRemoteTransitionFinishedCallback finishCallback) {
+ final ArrayMap<SurfaceControl, SurfaceControl> leashMap = new ArrayMap<>();
final RemoteAnimationTargetCompat[] appsCompat =
- RemoteAnimationTargetCompat.wrap(info, false /* wallpapers */);
+ RemoteAnimationTargetCompat.wrap(info, false /* wallpapers */, t, leashMap);
final RemoteAnimationTargetCompat[] wallpapersCompat =
- RemoteAnimationTargetCompat.wrap(info, true /* wallpapers */);
+ RemoteAnimationTargetCompat.wrap(info, true /* wallpapers */, t, leashMap);
// TODO(bc-unlock): Build wrapped object for non-apps target.
final RemoteAnimationTargetCompat[] nonAppsCompat =
new RemoteAnimationTargetCompat[0];
@@ -211,7 +213,7 @@
// Need to "boost" the closing things since that's what launcher expects.
for (int i = info.getChanges().size() - 1; i >= 0; --i) {
final TransitionInfo.Change change = info.getChanges().get(i);
- final SurfaceControl leash = change.getLeash();
+ final SurfaceControl leash = leashMap.get(change.getLeash());
final int mode = info.getChanges().get(i).getMode();
// Only deal with independent layers
if (!TransitionInfo.isIndependent(change, info)) continue;
@@ -227,14 +229,14 @@
}
} else {
if (launcherTask != null) {
- counterLauncher.addChild(t, launcherTask.getLeash());
+ counterLauncher.addChild(t, leashMap.get(launcherTask.getLeash()));
}
if (wallpaper != null && rotateDelta != 0 && wallpaper.getParent() != null) {
counterWallpaper.setup(t, info.getChange(wallpaper.getParent()).getLeash(),
rotateDelta, displayW, displayH);
if (counterWallpaper.mSurface != null) {
t.setLayer(counterWallpaper.mSurface, -1);
- counterWallpaper.addChild(t, wallpaper.getLeash());
+ counterWallpaper.addChild(t, leashMap.get(wallpaper.getLeash()));
}
}
}
@@ -252,6 +254,12 @@
for (int i = 0; i < info.getChanges().size(); ++i) {
info.getChanges().get(i).getLeash().release();
}
+ SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+ for (int i = 0; i < leashMap.size(); ++i) {
+ if (leashMap.keyAt(i) == leashMap.valueAt(i)) continue;
+ t.remove(leashMap.valueAt(i));
+ }
+ t.apply();
finishCallback.onTransitionFinished(null /* wct */);
} catch (RemoteException e) {
Log.e("ActivityOptionsCompat", "Failed to call app controlled animation"
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
index fcab71c..2407d21 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
@@ -17,11 +17,21 @@
package com.android.systemui.shared.system;
import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE;
+import static android.view.WindowManager.TRANSIT_CHANGE;
+import static android.view.WindowManager.TRANSIT_CLOSE;
+import static android.view.WindowManager.TRANSIT_OPEN;
+import static android.view.WindowManager.TRANSIT_TO_BACK;
+import static android.view.WindowManager.TRANSIT_TO_FRONT;
+import static android.window.TransitionInfo.FLAG_IS_WALLPAPER;
+import static android.window.TransitionInfo.FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT;
+import android.annotation.NonNull;
+import android.annotation.SuppressLint;
import android.app.ActivityManager;
import android.app.WindowConfiguration;
import android.graphics.Point;
import android.graphics.Rect;
+import android.util.ArrayMap;
import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
import android.view.WindowManager;
@@ -97,10 +107,94 @@
}
}
- public RemoteAnimationTargetCompat(TransitionInfo.Change change, int order) {
+
+ /**
+ * Almost a copy of Transitions#setupStartState.
+ * TODO: remove when there is proper cross-process transaction sync.
+ */
+ @SuppressLint("NewApi")
+ private static void setupLeash(@NonNull SurfaceControl leash,
+ @NonNull TransitionInfo.Change change, int layer,
+ @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction t) {
+ boolean isOpening = info.getType() == TRANSIT_OPEN || info.getType() == TRANSIT_TO_FRONT;
+ // Put animating stuff above this line and put static stuff below it.
+ int zSplitLine = info.getChanges().size();
+ // changes should be ordered top-to-bottom in z
+ final int mode = change.getMode();
+
+ // Don't move anything that isn't independent within its parents
+ if (!TransitionInfo.isIndependent(change, info)) {
+ if (mode == TRANSIT_OPEN || mode == TRANSIT_TO_FRONT || mode == TRANSIT_CHANGE) {
+ t.show(leash);
+ t.setPosition(leash, change.getEndRelOffset().x, change.getEndRelOffset().y);
+ }
+ return;
+ }
+
+ boolean hasParent = change.getParent() != null;
+
+ if (!hasParent) {
+ t.reparent(leash, info.getRootLeash());
+ t.setPosition(leash, change.getStartAbsBounds().left - info.getRootOffset().x,
+ change.getStartAbsBounds().top - info.getRootOffset().y);
+ }
+ t.show(leash);
+ // Put all the OPEN/SHOW on top
+ if (mode == TRANSIT_OPEN || mode == TRANSIT_TO_FRONT) {
+ if (isOpening) {
+ t.setLayer(leash, zSplitLine + info.getChanges().size() - layer);
+ if ((change.getFlags() & FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT) == 0) {
+ // if transferred, it should be left visible.
+ t.setAlpha(leash, 0.f);
+ }
+ } else {
+ // put on bottom and leave it visible
+ t.setLayer(leash, zSplitLine - layer);
+ }
+ } else if (mode == TRANSIT_CLOSE || mode == TRANSIT_TO_BACK) {
+ if (isOpening) {
+ // put on bottom and leave visible
+ t.setLayer(leash, zSplitLine - layer);
+ } else {
+ // put on top
+ t.setLayer(leash, zSplitLine + info.getChanges().size() - layer);
+ }
+ } else { // CHANGE
+ t.setLayer(leash, zSplitLine + info.getChanges().size() - layer);
+ }
+ }
+
+ @SuppressLint("NewApi")
+ private static SurfaceControl createLeash(TransitionInfo info, TransitionInfo.Change change,
+ int order, SurfaceControl.Transaction t) {
+ // TODO: once we can properly sync transactions across process, then get rid of this leash.
+ if (change.getParent() != null && (change.getFlags() & FLAG_IS_WALLPAPER) != 0) {
+ // Special case for wallpaper atm. Normally these are left alone; but, a quirk of
+ // making leashes means we have to handle them specially.
+ return change.getLeash();
+ }
+ SurfaceControl leashSurface = new SurfaceControl.Builder()
+ .setName(change.getLeash().toString() + "_transition-leash")
+ .setContainerLayer().setParent(change.getParent() == null ? info.getRootLeash()
+ : info.getChange(change.getParent()).getLeash()).build();
+ // Copied Transitions setup code (which expects bottom-to-top order, so we swap here)
+ setupLeash(leashSurface, change, info.getChanges().size() - order, info, t);
+ t.reparent(change.getLeash(), leashSurface);
+ t.setAlpha(change.getLeash(), 1.0f);
+ t.show(change.getLeash());
+ t.setPosition(change.getLeash(), 0, 0);
+ t.setLayer(change.getLeash(), 0);
+ return leashSurface;
+ }
+
+ public RemoteAnimationTargetCompat(TransitionInfo.Change change, int order,
+ TransitionInfo info, SurfaceControl.Transaction t) {
taskId = change.getTaskInfo() != null ? change.getTaskInfo().taskId : -1;
mode = newModeToLegacyMode(change.getMode());
- leash = new SurfaceControlCompat(change.getLeash());
+
+ // TODO: once we can properly sync transactions across process, then get rid of this leash.
+ leash = new SurfaceControlCompat(createLeash(info, change, order, t));
+
isTranslucent = (change.getFlags() & TransitionInfo.FLAG_TRANSLUCENT) != 0
|| (change.getFlags() & TransitionInfo.FLAG_SHOW_WALLPAPER) != 0;
clipRect = null;
@@ -139,15 +233,21 @@
*
* @param wallpapers If true, this will return wallpaper targets; otherwise it returns
* non-wallpaper targets.
+ * @param leashMap Temporary map of change leash -> launcher leash. Is an output, so should be
+ * populated by this function. If null, it is ignored.
*/
- public static RemoteAnimationTargetCompat[] wrap(TransitionInfo info, boolean wallpapers) {
+ public static RemoteAnimationTargetCompat[] wrap(TransitionInfo info, boolean wallpapers,
+ SurfaceControl.Transaction t, ArrayMap<SurfaceControl, SurfaceControl> leashMap) {
final ArrayList<RemoteAnimationTargetCompat> out = new ArrayList<>();
for (int i = 0; i < info.getChanges().size(); i++) {
boolean changeIsWallpaper =
(info.getChanges().get(i).getFlags() & TransitionInfo.FLAG_IS_WALLPAPER) != 0;
if (wallpapers != changeIsWallpaper) continue;
out.add(new RemoteAnimationTargetCompat(info.getChanges().get(i),
- info.getChanges().size() - i));
+ info.getChanges().size() - i, info, t));
+ if (leashMap == null) continue;
+ leashMap.put(info.getChanges().get(i).getLeash(),
+ out.get(out.size() - 1).leash.mSurfaceControl);
}
return out.toArray(new RemoteAnimationTargetCompat[out.size()]);
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java
index 5708855..653d730 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java
@@ -29,6 +29,7 @@
import android.os.IBinder;
import android.os.Parcelable;
import android.os.RemoteException;
+import android.util.ArrayMap;
import android.util.Log;
import android.view.IRecentsAnimationController;
import android.view.SurfaceControl;
@@ -108,10 +109,11 @@
public void startAnimation(IBinder transition, TransitionInfo info,
SurfaceControl.Transaction t,
IRemoteTransitionFinishedCallback finishedCallback) {
+ final ArrayMap<SurfaceControl, SurfaceControl> leashMap = new ArrayMap<>();
final RemoteAnimationTargetCompat[] apps =
- RemoteAnimationTargetCompat.wrap(info, false /* wallpapers */);
+ RemoteAnimationTargetCompat.wrap(info, false /* wallpapers */, t, leashMap);
final RemoteAnimationTargetCompat[] wallpapers =
- RemoteAnimationTargetCompat.wrap(info, true /* wallpapers */);
+ RemoteAnimationTargetCompat.wrap(info, true /* wallpapers */, t, leashMap);
// TODO(b/177438007): Move this set-up logic into launcher's animation impl.
mToken = transition;
// This transition is for opening recents, so recents is on-top. We want to draw
@@ -120,7 +122,8 @@
for (int i = info.getChanges().size() - 1; i >= 0; --i) {
final TransitionInfo.Change change = info.getChanges().get(i);
if (change.getMode() == TRANSIT_CLOSE || change.getMode() == TRANSIT_TO_BACK) {
- t.setLayer(change.getLeash(), info.getChanges().size() * 3 - i);
+ t.setLayer(leashMap.get(change.getLeash()),
+ info.getChanges().size() * 3 - i);
if (change.getTaskInfo() != null) {
pausingTask = change.getTaskInfo().token;
}
@@ -131,7 +134,8 @@
t.setAlpha(wallpapers[i].leash.mSurfaceControl, 1);
}
t.apply();
- mRecentsSession.setup(controller, info, finishedCallback, pausingTask);
+ mRecentsSession.setup(controller, info, finishedCallback, pausingTask,
+ leashMap);
recents.onAnimationStart(mRecentsSession, apps, wallpapers, new Rect(0, 0, 0, 0),
new Rect());
}
@@ -173,9 +177,11 @@
private WindowContainerToken mPausingTask = null;
private TransitionInfo mInfo = null;
private SurfaceControl mOpeningLeash = null;
+ private ArrayMap<SurfaceControl, SurfaceControl> mLeashMap = null;
void setup(RecentsAnimationControllerCompat wrapped, TransitionInfo info,
- IRemoteTransitionFinishedCallback finishCB, WindowContainerToken pausingTask) {
+ IRemoteTransitionFinishedCallback finishCB, WindowContainerToken pausingTask,
+ ArrayMap<SurfaceControl, SurfaceControl> leashMap) {
if (mInfo != null) {
throw new IllegalStateException("Trying to run a new recents animation while"
+ " recents is already active.");
@@ -184,6 +190,7 @@
mInfo = info;
mFinishCB = finishCB;
mPausingTask = pausingTask;
+ mLeashMap = leashMap;
}
@SuppressLint("NewApi")
@@ -211,11 +218,14 @@
}
// We are receiving a new opening task, so convert to onTaskAppeared.
final int layer = mInfo.getChanges().size() * 3;
- t.reparent(mOpeningLeash, mInfo.getRootLeash());
- t.setLayer(mOpeningLeash, layer);
- t.hide(mOpeningLeash);
+ final RemoteAnimationTargetCompat target = new RemoteAnimationTargetCompat(
+ openingTask, layer, mInfo, t);
+ mLeashMap.put(mOpeningLeash, target.leash.mSurfaceControl);
+ t.reparent(target.leash.mSurfaceControl, mInfo.getRootLeash());
+ t.setLayer(target.leash.mSurfaceControl, layer);
+ t.hide(target.leash.mSurfaceControl);
t.apply();
- recents.onTaskAppeared(new RemoteAnimationTargetCompat(openingTask, layer));
+ recents.onTaskAppeared(target);
return true;
}
@@ -236,9 +246,9 @@
}
@Override public void setFinishTaskTransaction(int taskId,
- PictureInPictureSurfaceTransaction finishTransaction) {
+ PictureInPictureSurfaceTransaction finishTransaction, SurfaceControl overlay) {
if (mWrapped != null) {
- mWrapped.setFinishTaskTransaction(taskId, finishTransaction);
+ mWrapped.setFinishTaskTransaction(taskId, finishTransaction, overlay);
}
}
@@ -272,6 +282,12 @@
}
// Release surface references now. This is apparently to free GPU
// memory while doing quick operations (eg. during CTS).
+ SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+ for (int i = 0; i < mLeashMap.size(); ++i) {
+ if (mLeashMap.keyAt(i) == mLeashMap.valueAt(i)) continue;
+ t.remove(mLeashMap.valueAt(i));
+ }
+ t.apply();
for (int i = 0; i < mInfo.getChanges().size(); ++i) {
mInfo.getChanges().get(i).getLeash().release();
}
@@ -281,6 +297,7 @@
mPausingTask = null;
mInfo = null;
mOpeningLeash = null;
+ mLeashMap = null;
}
@Override public void setDeferCancelUntilNextTransition(boolean defer, boolean screenshot) {
diff --git a/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java b/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java
index 825e008..332de6c 100644
--- a/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java
+++ b/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java
@@ -37,7 +37,8 @@
import java.util.TimeZone;
/**
- * Controller for an AnimatableClockView. Instantiated by {@link KeyguardClockSwitchController}.
+ * Controller for an AnimatableClockView on the keyguard. Instantiated by
+ * {@link KeyguardClockSwitchController}.
*/
public class AnimatableClockController extends ViewController<AnimatableClockView> {
private static final int FORMAT_NUMBER = 1234567890;
@@ -46,6 +47,7 @@
private final BroadcastDispatcher mBroadcastDispatcher;
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
private final KeyguardBypassController mBypassController;
+ private final BatteryController mBatteryController;
private final int mDozingColor = Color.WHITE;
private int mLockScreenColor;
@@ -53,6 +55,7 @@
private boolean mIsCharging;
private float mDozeAmount;
private Locale mLocale;
+ private boolean mAttached; // if keyguard isn't showing, mAttached = false
private final NumberFormat mBurmeseNf = NumberFormat.getInstance(Locale.forLanguageTag("my"));
private final String mBurmeseNumerals;
@@ -73,44 +76,47 @@
mBroadcastDispatcher = broadcastDispatcher;
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mBypassController = bypassController;
+ mBatteryController = batteryController;
mBurmeseNumerals = mBurmeseNf.format(FORMAT_NUMBER);
mBurmeseLineSpacing = getContext().getResources().getFloat(
R.dimen.keyguard_clock_line_spacing_scale_burmese);
mDefaultLineSpacing = getContext().getResources().getFloat(
R.dimen.keyguard_clock_line_spacing_scale);
-
- batteryController.addCallback(new BatteryController.BatteryStateChangeCallback() {
- @Override
- public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
- if (!mIsCharging && charging) {
- mView.animateCharge(mIsDozing);
- }
- mIsCharging = charging;
- }
- });
}
- private BroadcastReceiver mLocaleBroadcastReceiver = new BroadcastReceiver() {
+ private final BatteryController.BatteryStateChangeCallback mBatteryCallback =
+ new BatteryController.BatteryStateChangeCallback() {
+ @Override
+ public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
+ if (!mIsCharging && charging) {
+ mView.animateCharge(mIsDozing);
+ }
+ mIsCharging = charging;
+ }
+ };
+
+ private final BroadcastReceiver mLocaleBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
updateLocale();
}
};
- @Override
- protected void onViewAttached() {
- updateLocale();
- mBroadcastDispatcher.registerReceiver(mLocaleBroadcastReceiver,
- new IntentFilter(Intent.ACTION_LOCALE_CHANGED));
- mStatusBarStateController.addCallback(mStatusBarStateListener);
- mIsDozing = mStatusBarStateController.isDozing();
- mDozeAmount = mStatusBarStateController.getDozeAmount();
- mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateMonitorCallback);
-
- refreshTime();
- initColors();
- }
+ private final KeyguardUpdateMonitorCallback mKeyguardPersistentCallback =
+ new KeyguardUpdateMonitorCallback() {
+ @Override
+ public void onKeyguardVisibilityChanged(boolean showing) {
+ // call attached/detached methods on visibility changes. benefits include:
+ // - no animations when keyguard/clock view aren't visible
+ // - resets state when keyguard is visible again (ie: font weight)
+ if (showing) {
+ onViewAttached();
+ } else {
+ onViewDetached();
+ }
+ }
+ };
private final KeyguardUpdateMonitorCallback mKeyguardUpdateMonitorCallback =
new KeyguardUpdateMonitorCallback() {
@@ -125,10 +131,46 @@
};
@Override
+ protected void onViewAttached() {
+ if (mAttached) {
+ return;
+ }
+ mAttached = true;
+ updateLocale();
+ mBroadcastDispatcher.registerReceiver(mLocaleBroadcastReceiver,
+ new IntentFilter(Intent.ACTION_LOCALE_CHANGED));
+ mStatusBarStateController.addCallback(mStatusBarStateListener);
+ mIsDozing = mStatusBarStateController.isDozing();
+ mDozeAmount = mStatusBarStateController.getDozeAmount();
+ mBatteryController.addCallback(mBatteryCallback);
+ mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateMonitorCallback);
+
+ mKeyguardUpdateMonitor.removeCallback(mKeyguardPersistentCallback);
+ mKeyguardUpdateMonitor.registerCallback(mKeyguardPersistentCallback);
+
+ refreshTime();
+ initColors();
+ }
+
+ @Override
protected void onViewDetached() {
+ if (!mAttached) {
+ return;
+ }
+
+ mAttached = false;
mBroadcastDispatcher.unregisterReceiver(mLocaleBroadcastReceiver);
mStatusBarStateController.removeCallback(mStatusBarStateListener);
mKeyguardUpdateMonitor.removeCallback(mKeyguardUpdateMonitorCallback);
+ mBatteryController.removeCallback(mBatteryCallback);
+ if (!mView.isAttachedToWindow()) {
+ mKeyguardUpdateMonitor.removeCallback(mKeyguardPersistentCallback);
+ }
+ }
+
+ /** Animate the clock appearance */
+ public void animateAppear() {
+ if (!mIsDozing) mView.animateAppearOnLockscreen();
}
/**
diff --git a/packages/SystemUI/src/com/android/keyguard/AnimatableClockView.java b/packages/SystemUI/src/com/android/keyguard/AnimatableClockView.java
index 41d991c..63867c0 100644
--- a/packages/SystemUI/src/com/android/keyguard/AnimatableClockView.java
+++ b/packages/SystemUI/src/com/android/keyguard/AnimatableClockView.java
@@ -44,6 +44,7 @@
private static final CharSequence SINGLE_LINE_FORMAT_12_HOUR = "h:mm";
private static final CharSequence SINGLE_LINE_FORMAT_24_HOUR = "HH:mm";
private static final long DOZE_ANIM_DURATION = 300;
+ private static final long APPEAR_ANIM_DURATION = 350;
private static final long CHARGE_ANIM_DURATION_PHASE_0 = 500;
private static final long CHARGE_ANIM_DURATION_PHASE_1 = 1000;
@@ -156,6 +157,30 @@
mLockScreenColor = lockScreenColor;
}
+ void animateAppearOnLockscreen() {
+ if (mTextAnimator == null) {
+ return;
+ }
+
+ setTextStyle(
+ mDozingWeight,
+ -1 /* text size, no update */,
+ mLockScreenColor,
+ false /* animate */,
+ 0 /* duration */,
+ 0 /* delay */,
+ null /* onAnimationEnd */);
+
+ setTextStyle(
+ mLockScreenWeight,
+ -1 /* text size, no update */,
+ mLockScreenColor,
+ true, /* animate */
+ APPEAR_ANIM_DURATION,
+ 0 /* delay */,
+ null /* onAnimationEnd */);
+ }
+
void animateDisappear() {
if (mTextAnimator == null) {
return;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
index 407146f..1c4cde8 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
@@ -35,6 +35,7 @@
private static final long CLOCK_OUT_MILLIS = 150;
private static final long CLOCK_IN_MILLIS = 200;
+ private static final long SMARTSPACE_MOVE_MILLIS = 350;
/**
* Optional/alternative clock injected via plugin.
@@ -54,6 +55,8 @@
* show it below the alternate clock.
*/
private View mKeyguardStatusArea;
+ /** Mutually exclusive with mKeyguardStatusArea */
+ private View mSmartspaceView;
/**
* Maintain state so that a newly connected plugin can be initialized.
@@ -67,6 +70,7 @@
private AnimatorSet mClockInAnim = null;
private AnimatorSet mClockOutAnim = null;
+ private ObjectAnimator mSmartspaceAnim = null;
/**
* If the Keyguard Slice has a header (big center-aligned text.)
@@ -177,17 +181,22 @@
private void animateClockChange(boolean useLargeClock) {
if (mClockInAnim != null) mClockInAnim.cancel();
if (mClockOutAnim != null) mClockOutAnim.cancel();
+ if (mSmartspaceAnim != null) mSmartspaceAnim.cancel();
View in, out;
int direction = 1;
+ float smartspaceYTranslation;
if (useLargeClock) {
out = mClockFrame;
in = mLargeClockFrame;
if (indexOfChild(in) == -1) addView(in);
direction = -1;
+ smartspaceYTranslation = mSmartspaceView == null ? 0
+ : mClockFrame.getY() - mSmartspaceView.getY();
} else {
in = mClockFrame;
out = mLargeClockFrame;
+ smartspaceYTranslation = 0f;
// Must remove in order for notifications to appear in the proper place
removeView(out);
@@ -222,6 +231,19 @@
mClockInAnim.start();
mClockOutAnim.start();
+
+ if (mSmartspaceView != null) {
+ mSmartspaceAnim = ObjectAnimator.ofFloat(mSmartspaceView, View.TRANSLATION_Y,
+ smartspaceYTranslation);
+ mSmartspaceAnim.setDuration(SMARTSPACE_MOVE_MILLIS);
+ mSmartspaceAnim.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
+ mSmartspaceAnim.addListener(new AnimatorListenerAdapter() {
+ public void onAnimationEnd(Animator animation) {
+ mSmartspaceAnim = null;
+ }
+ });
+ mSmartspaceAnim.start();
+ }
}
/**
@@ -237,15 +259,18 @@
}
/**
- * Set whether or not the lock screen is showing notifications.
+ * Based upon whether notifications are showing or not, display/hide the large clock and
+ * the smaller version.
*/
- void setHasVisibleNotifications(boolean hasVisibleNotifications) {
+ boolean willSwitchToLargeClock(boolean hasVisibleNotifications) {
if (hasVisibleNotifications == mHasVisibleNotifications) {
- return;
+ return false;
}
- animateClockChange(!hasVisibleNotifications);
+ boolean useLargeClock = !hasVisibleNotifications;
+ animateClockChange(useLargeClock);
mHasVisibleNotifications = hasVisibleNotifications;
+ return useLargeClock;
}
public Paint getPaint() {
@@ -303,6 +328,10 @@
}
}
+ void setSmartspaceView(View smartspaceView) {
+ mSmartspaceView = smartspaceView;
+ }
+
void updateColors(ColorExtractor.GradientColors colors) {
mSupportsDarkText = colors.supportsDarkText();
mColorPalette = colors.getColorPalette();
@@ -317,6 +346,7 @@
pw.println(" mClockFrame: " + mClockFrame);
pw.println(" mLargeClockFrame: " + mLargeClockFrame);
pw.println(" mKeyguardStatusArea: " + mKeyguardStatusArea);
+ pw.println(" mSmartspaceView: " + mSmartspaceView);
pw.println(" mDarkAmount: " + mDarkAmount);
pw.println(" mSupportsDarkText: " + mSupportsDarkText);
pw.println(" mColorPalette: " + Arrays.toString(mColorPalette));
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
index baf3458..aa7f9a2 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
@@ -124,16 +124,6 @@
@Override
public void onInit() {
mKeyguardSliceViewController.init();
- }
-
- @Override
- protected void onViewAttached() {
- if (CUSTOM_CLOCKS_ENABLED) {
- mClockManager.addOnClockChangedListener(mClockChangedListener);
- }
- mColorExtractor.addOnColorsChangedListener(mColorsListener);
- mView.updateColors(getGradientColors());
- updateAodIcons();
mClockFrame = mView.findViewById(R.id.lockscreen_clock_view);
mLargeClockFrame = mView.findViewById(R.id.lockscreen_clock_view_large);
@@ -157,6 +147,16 @@
mKeyguardUpdateMonitor,
mBypassController);
mLargeClockViewController.init();
+ }
+
+ @Override
+ protected void onViewAttached() {
+ if (CUSTOM_CLOCKS_ENABLED) {
+ mClockManager.addOnClockChangedListener(mClockChangedListener);
+ }
+ mColorExtractor.addOnColorsChangedListener(mColorsListener);
+ mView.updateColors(getGradientColors());
+ updateAodIcons();
if (mSmartspaceController.isEnabled()) {
mSmartspaceView = mSmartspaceController.buildAndConnectView(mView);
@@ -185,6 +185,8 @@
lp = (RelativeLayout.LayoutParams) nic.getLayoutParams();
lp.addRule(RelativeLayout.BELOW, mSmartspaceView.getId());
nic.setLayoutParams(lp);
+
+ mView.setSmartspaceView(mSmartspaceView);
}
}
@@ -220,7 +222,9 @@
* Set whether or not the lock screen is showing notifications.
*/
public void setHasVisibleNotifications(boolean hasVisibleNotifications) {
- mView.setHasVisibleNotifications(hasVisibleNotifications);
+ if (mView.willSwitchToLargeClock(hasVisibleNotifications)) {
+ mLargeClockViewController.animateAppear();
+ }
}
/**
@@ -255,6 +259,9 @@
mClockViewController.refreshTime();
mLargeClockViewController.refreshTime();
}
+ if (mSmartspaceController != null) {
+ mSmartspaceController.requestSmartspaceUpdate();
+ }
mView.refresh();
}
@@ -303,8 +310,6 @@
NotificationIconContainer nic = (NotificationIconContainer)
mView.findViewById(
com.android.systemui.R.id.left_aligned_notification_icon_container);
-
- // alt icon area is set in KeyguardClockSwitchController
mNotificationIconAreaController.setupAodIcons(nic);
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java
index d06c8bc..3ebd652 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java
@@ -481,7 +481,7 @@
if (resources.getBoolean(R.bool.can_use_one_handed_bouncer)
&& resources.getBoolean(
- com.android.internal.R.bool.config_enableOneHandedKeyguard)) {
+ com.android.internal.R.bool.config_enableDynamicKeyguardPositioning)) {
gravity = resources.getInteger(
R.integer.keyguard_host_view_one_handed_gravity);
} else {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index 54ecf95..ca4d73b 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -278,7 +278,7 @@
private boolean canUseOneHandedBouncer() {
// Is it enabled?
if (!getResources().getBoolean(
- com.android.internal.R.bool.config_enableOneHandedKeyguard)) {
+ com.android.internal.R.bool.config_enableDynamicKeyguardPositioning)) {
return false;
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
index 3a3f2fc..388c085 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
@@ -198,6 +198,13 @@
}
/**
+ * @return {@code true} if we are currently animating the screen off from unlock
+ */
+ public boolean isAnimatingScreenOffFromUnlocked() {
+ return mKeyguardVisibilityHelper.isAnimatingScreenOffFromUnlocked();
+ }
+
+ /**
* Set the visibility of the keyguard status view based on some new state.
*/
public void setKeyguardStatusViewVisibility(
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 64bc77f..44df02a 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -252,7 +252,6 @@
@Override
public void onStateChanged(int newState) {
mStatusBarState = newState;
- updateBiometricListeningState();
}
@Override
@@ -2199,7 +2198,7 @@
&& !mSwitchingUser && !isFaceDisabled(user) && becauseCannotSkipBouncer
&& !mKeyguardGoingAway && mBiometricEnabledForUser.get(user) && !mLockIconPressed
&& strongAuthAllowsScanning && mIsPrimaryUser
- && !mSecureCameraLaunched;
+ && (!mSecureCameraLaunched || mOccludingAppRequestingFace);
// Aggregate relevant fields for debug logging.
if (DEBUG_FACE || DEBUG_SPEW) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java b/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java
index 6aca5a7..b6a58dc 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java
@@ -22,6 +22,9 @@
import com.android.systemui.animation.Interpolators;
import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.notification.AnimatableProperty;
+import com.android.systemui.statusbar.notification.PropertyAnimator;
+import com.android.systemui.statusbar.notification.stack.AnimationProperties;
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -37,6 +40,8 @@
private final DozeParameters mDozeParameters;
private boolean mKeyguardViewVisibilityAnimating;
private boolean mLastOccludedState = false;
+ private boolean mAnimatingScreenOff;
+ private final AnimationProperties mAnimationProperties = new AnimationProperties();
public KeyguardVisibilityHelper(View view, KeyguardStateController keyguardStateController,
DozeParameters dozeParameters) {
@@ -89,12 +94,21 @@
} 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()
.alpha(0)
- .translationYBy(-mView.getHeight() * 0.05f)
.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN)
- .setDuration(125)
- .setStartDelay(0)
+ .setDuration(duration)
+ .setStartDelay(delay)
.withEndAction(mAnimateKeyguardStatusViewInvisibleEndRunnable)
.start();
} else if (mLastOccludedState && !isOccluded) {
@@ -110,20 +124,30 @@
.start();
} else if (mDozeParameters.shouldControlUnlockedScreenOff()) {
mKeyguardViewVisibilityAnimating = true;
+ mAnimatingScreenOff = true;
mView.setVisibility(View.VISIBLE);
mView.setAlpha(0f);
+ float currentY = mView.getY();
+ mView.setY(currentY - mView.getHeight() * 0.1f);
+ int duration = StackStateAnimator.ANIMATION_DURATION_WAKEUP;
+ int delay = (int) (duration * .6f);
+ // 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, currentY,
+ mAnimationProperties,
+ true /* animate */);
- float curTranslationY = mView.getTranslationY();
- mView.setTranslationY(curTranslationY - mView.getHeight() * 0.1f);
mView.animate()
- .setStartDelay((int) (StackStateAnimator.ANIMATION_DURATION_WAKEUP * .6f))
- .setDuration(StackStateAnimator.ANIMATION_DURATION_WAKEUP)
+ .setStartDelay(delay)
+ .setDuration(duration)
.setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
.alpha(1f)
- .translationY(curTranslationY)
.withEndAction(mAnimateKeyguardStatusViewVisibleEndRunnable)
.start();
+
} else {
mView.setVisibility(View.VISIBLE);
mView.setAlpha(1f);
@@ -148,5 +172,13 @@
private final Runnable mAnimateKeyguardStatusViewVisibleEndRunnable = () -> {
mKeyguardViewVisibilityAnimating = false;
+ mAnimatingScreenOff = false;
};
+
+ /**
+ * @return {@code true} if we are currently animating the screen off from unlock
+ */
+ public boolean isAnimatingScreenOffFromUnlocked() {
+ return mAnimatingScreenOff;
+ }
}
diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
index b367bdf..0ea01fd 100644
--- a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
@@ -45,6 +45,7 @@
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.phone.dagger.StatusBarComponent;
+import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.ViewController;
@@ -68,6 +69,7 @@
@NonNull private final FalsingManager mFalsingManager;
@NonNull private final AuthController mAuthController;
@NonNull private final AccessibilityManager mAccessibilityManager;
+ @NonNull private final ConfigurationController mConfigurationController;
private boolean mHasUdfpsOrFaceAuthFeatures;
private boolean mUdfpsEnrolled;
@@ -103,7 +105,8 @@
@NonNull FalsingManager falsingManager,
@NonNull AuthController authController,
@NonNull DumpManager dumpManager,
- @NonNull AccessibilityManager accessibilityManager
+ @NonNull AccessibilityManager accessibilityManager,
+ @NonNull ConfigurationController configurationController
) {
super(view);
mStatusBarStateController = statusBarStateController;
@@ -113,6 +116,7 @@
mKeyguardStateController = keyguardStateController;
mFalsingManager = falsingManager;
mAccessibilityManager = accessibilityManager;
+ mConfigurationController = configurationController;
final Context context = view.getContext();
mButton = context.getResources().getDrawable(
@@ -145,7 +149,13 @@
final boolean hasUdfps = mAuthController.getUdfpsSensorLocation() != null;
mHasUdfpsOrFaceAuthFeatures = hasFaceAuth || hasUdfps;
if (!mHasUdfpsOrFaceAuthFeatures) {
- ((ViewGroup) mView.getParent()).removeView(mView);
+ // Posting since removing a view in the middle of onAttach can lead to a crash in the
+ // iteration loop when the view isn't last
+ mView.setVisibility(View.GONE);
+ mView.post(() -> {
+ mView.setVisibility(View.VISIBLE);
+ ((ViewGroup) mView.getParent()).removeView(mView);
+ });
return;
}
@@ -172,10 +182,8 @@
mCanDismissLockScreen = mKeyguardStateController.canDismissLockScreen();
mStatusBarState = mStatusBarStateController.getState();
- mUnlockIcon.setTint(Utils.getColorAttrDefaultColor(mView.getContext(),
- R.attr.wallpaperTextColorAccent));
- mLockIcon.setTint(Utils.getColorAttrDefaultColor(mView.getContext(),
- R.attr.wallpaperTextColorAccent));
+ updateColors();
+ mConfigurationController.addCallback(mConfigurationListener);
mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateMonitorCallback);
mStatusBarStateController.addCallback(mStatusBarStateListener);
@@ -188,6 +196,7 @@
@Override
protected void onViewDetached() {
+ mConfigurationController.removeCallback(mConfigurationListener);
mKeyguardUpdateMonitor.removeCallback(mKeyguardUpdateMonitorCallback);
mStatusBarStateController.removeCallback(mStatusBarStateListener);
mKeyguardStateController.removeCallback(mKeyguardStateCallback);
@@ -300,6 +309,13 @@
&& !mKeyguardStateController.isKeyguardGoingAway();
}
+ private void updateColors() {
+ final int color = Utils.getColorAttrDefaultColor(mView.getContext(),
+ R.attr.wallpaperTextColorAccent);
+ mUnlockIcon.setTint(color);
+ mLockIcon.setTint(color);
+ }
+
@Override
public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) {
pw.println(" mShowBouncerButton: " + mShowButton);
@@ -379,6 +395,24 @@
}
};
+ private final ConfigurationController.ConfigurationListener mConfigurationListener =
+ new ConfigurationController.ConfigurationListener() {
+ @Override
+ public void onUiModeChanged() {
+ updateColors();
+ }
+
+ @Override
+ public void onThemeChanged() {
+ updateColors();
+ }
+
+ @Override
+ public void onOverlayChanged() {
+ updateColors();
+ }
+ };
+
private final AccessibilityManager.TouchExplorationStateChangeListener
mTouchExplorationStateChangeListener = enabled -> updateClickListener();
}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java
index 9f77b7d..ee7eb4b 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java
@@ -22,14 +22,17 @@
import android.annotation.UiContext;
import android.content.Context;
import android.content.pm.ActivityInfo;
+import android.graphics.Insets;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.UserHandle;
import android.provider.Settings;
+import android.util.MathUtils;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
+import android.view.WindowInsets;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.view.accessibility.AccessibilityManager;
@@ -38,6 +41,7 @@
import android.widget.ImageView;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
import com.android.systemui.R;
import java.util.Collections;
@@ -45,8 +49,8 @@
/**
* Shows/hides a {@link android.widget.ImageView} on the screen and changes the values of
* {@link Settings.Secure#ACCESSIBILITY_MAGNIFICATION_MODE} when the UI is toggled.
- * The button icon is movable by dragging. And the button UI would automatically be dismissed after
- * displaying for a period of time.
+ * The button icon is movable by dragging and it would not overlap navigation bar window.
+ * And the button UI would automatically be dismissed after displaying for a period of time.
*/
class MagnificationModeSwitch implements MagnificationGestureDetector.OnGestureListener {
@@ -64,25 +68,30 @@
private final AccessibilityManager mAccessibilityManager;
private final WindowManager mWindowManager;
private final ImageView mImageView;
+ private final Runnable mWindowInsetChangeRunnable;
+ private final SfVsyncFrameCallbackProvider mSfVsyncFrameProvider;
private int mMagnificationMode = Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
private final LayoutParams mParams;
+ @VisibleForTesting
+ final Rect mDraggableWindowBounds = new Rect();
private boolean mIsVisible = false;
private final MagnificationGestureDetector mGestureDetector;
private boolean mSingleTapDetected = false;
+ private boolean mToLeftScreenEdge = false;
MagnificationModeSwitch(@UiContext Context context) {
- this(context, createView(context));
+ this(context, createView(context), new SfVsyncFrameCallbackProvider());
}
@VisibleForTesting
- MagnificationModeSwitch(Context context, @NonNull ImageView imageView) {
+ MagnificationModeSwitch(Context context, @NonNull ImageView imageView,
+ SfVsyncFrameCallbackProvider sfVsyncFrameProvider) {
mContext = context;
mAccessibilityManager = mContext.getSystemService(AccessibilityManager.class);
- mWindowManager = (WindowManager) mContext.getSystemService(
- Context.WINDOW_SERVICE);
+ mWindowManager = mContext.getSystemService(WindowManager.class);
+ mSfVsyncFrameProvider = sfVsyncFrameProvider;
mParams = createLayoutParams(context);
mImageView = imageView;
- applyResourcesValues();
mImageView.setOnTouchListener(this::onTouch);
mImageView.setAccessibilityDelegate(new View.AccessibilityDelegate() {
@Override
@@ -107,6 +116,15 @@
return super.performAccessibilityAction(host, action, args);
}
});
+ mWindowInsetChangeRunnable = this::onWindowInsetChanged;
+ mImageView.setOnApplyWindowInsetsListener((v, insets) -> {
+ // Adds a pending post check to avoiding redundant calculation because this callback
+ // is sent frequently when the switch icon window dragged by the users.
+ if (!mImageView.getHandler().hasCallbacks(mWindowInsetChangeRunnable)) {
+ mImageView.getHandler().post(mWindowInsetChangeRunnable);
+ }
+ return v.onApplyWindowInsets(insets);
+ });
mFadeInAnimationTask = () -> {
mImageView.animate()
@@ -133,11 +151,17 @@
return mContext.getResources().getString(stringId);
}
- private void applyResourcesValues() {
- final int padding = mContext.getResources().getDimensionPixelSize(
- R.dimen.magnification_switch_button_padding);
- mImageView.setPadding(padding, padding, padding, padding);
- mImageView.setImageResource(getIconResId(mMagnificationMode));
+ private void applyResourcesValuesWithDensityChanged() {
+ final int size = mContext.getResources().getDimensionPixelSize(
+ R.dimen.magnification_switch_button_size);
+ mParams.height = size;
+ mParams.width = size;
+ if (mIsVisible) {
+ stickToScreenEdge(mToLeftScreenEdge);
+ // Reset button to make its window layer always above the mirror window.
+ removeButton();
+ showButton(mMagnificationMode, /* resetPosition= */false);
+ }
}
private boolean onTouch(View v, MotionEvent event) {
@@ -168,6 +192,12 @@
@Override
public boolean onFinish(float xOffset, float yOffset) {
+ if (mIsVisible) {
+ final int windowWidth = mWindowManager.getCurrentWindowMetrics().getBounds().width();
+ final int halfWindowWidth = windowWidth / 2;
+ mToLeftScreenEdge = (mParams.x < halfWindowWidth);
+ stickToScreenEdge(mToLeftScreenEdge);
+ }
if (!mSingleTapDetected) {
showButton(mMagnificationMode);
}
@@ -175,10 +205,18 @@
return true;
}
+ private void stickToScreenEdge(boolean toLeftScreenEdge) {
+ mParams.x = toLeftScreenEdge
+ ? mDraggableWindowBounds.left : mDraggableWindowBounds.right;
+ updateButtonViewLayoutIfNeeded();
+ }
+
private void moveButton(float offsetX, float offsetY) {
- mParams.x -= offsetX;
- mParams.y -= offsetY;
- mWindowManager.updateViewLayout(mImageView, mParams);
+ mSfVsyncFrameProvider.postFrameCallback(l -> {
+ mParams.x += offsetX;
+ mParams.y += offsetY;
+ updateButtonViewLayoutIfNeeded();
+ });
}
void removeButton() {
@@ -193,16 +231,32 @@
mImageView.setAlpha(0f);
mWindowManager.removeView(mImageView);
mIsVisible = false;
- mParams.x = 0;
- mParams.y = 0;
}
void showButton(int mode) {
+ showButton(mode, true);
+ }
+
+ /**
+ * Shows magnification switch button for the specified magnification mode.
+ * When the button is going to be visible by calling this method, the layout position can be
+ * reset depending on the flag.
+ *
+ * @param mode The magnification mode
+ * @param resetPosition if the button position needs be reset
+ */
+ private void showButton(int mode, boolean resetPosition) {
if (mMagnificationMode != mode) {
mMagnificationMode = mode;
mImageView.setImageResource(getIconResId(mode));
}
if (!mIsVisible) {
+ if (resetPosition) {
+ mDraggableWindowBounds.set(getDraggableWindowBounds());
+ mParams.x = mDraggableWindowBounds.right;
+ mParams.y = mDraggableWindowBounds.bottom;
+ mToLeftScreenEdge = false;
+ }
mWindowManager.addView(mImageView, mParams);
// Exclude magnification switch button from system gesture area.
setSystemGestureExclusion();
@@ -229,12 +283,7 @@
void onConfigurationChanged(int configDiff) {
if ((configDiff & ActivityInfo.CONFIG_DENSITY) != 0) {
- applyResourcesValues();
- if (mIsVisible) {
- mWindowManager.updateViewLayout(mImageView, mParams);
- // Exclude magnification switch button from system gesture area.
- setSystemGestureExclusion();
- }
+ applyResourcesValuesWithDensityChanged();
return;
}
if ((configDiff & ActivityInfo.CONFIG_LOCALE) != 0) {
@@ -243,6 +292,25 @@
}
}
+ private void onWindowInsetChanged() {
+ final Rect newBounds = getDraggableWindowBounds();
+ if (mDraggableWindowBounds.equals(newBounds)) {
+ return;
+ }
+ mDraggableWindowBounds.set(newBounds);
+ stickToScreenEdge(mToLeftScreenEdge);
+ }
+
+ private void updateButtonViewLayoutIfNeeded() {
+ if (mIsVisible) {
+ mParams.x = MathUtils.constrain(mParams.x, mDraggableWindowBounds.left,
+ mDraggableWindowBounds.right);
+ mParams.y = MathUtils.constrain(mParams.y, mDraggableWindowBounds.top,
+ mDraggableWindowBounds.bottom);
+ mWindowManager.updateViewLayout(mImageView, mParams);
+ }
+ }
+
private void updateAccessibilityWindowTitle() {
mParams.accessibilityTitle = getAccessibilityWindowTitle(mContext);
if (mIsVisible) {
@@ -283,17 +351,34 @@
}
private static LayoutParams createLayoutParams(Context context) {
+ final int size = context.getResources().getDimensionPixelSize(
+ R.dimen.magnification_switch_button_size);
final LayoutParams params = new LayoutParams(
- LayoutParams.WRAP_CONTENT,
- LayoutParams.WRAP_CONTENT,
+ size,
+ size,
LayoutParams.TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY,
LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSPARENT);
- params.gravity = Gravity.BOTTOM | Gravity.RIGHT;
+ params.gravity = Gravity.TOP | Gravity.LEFT;
params.accessibilityTitle = getAccessibilityWindowTitle(context);
return params;
}
+ private Rect getDraggableWindowBounds() {
+ final int layoutMargin = mContext.getResources().getDimensionPixelSize(
+ R.dimen.magnification_switch_button_margin);
+ final Rect boundRect = new Rect(mWindowManager.getCurrentWindowMetrics().getBounds());
+ final Insets systemBars =
+ mWindowManager.getCurrentWindowMetrics().getWindowInsets()
+ .getInsetsIgnoringVisibility(WindowInsets.Type.systemBars());
+ final Rect insets = new Rect(layoutMargin,
+ systemBars.top + layoutMargin,
+ mParams.width + layoutMargin,
+ mParams.height + layoutMargin + systemBars.bottom);
+ boundRect.inset(insets);
+ return boundRect;
+ }
+
private static String getAccessibilityWindowTitle(Context context) {
return context.getString(com.android.internal.R.string.android_system_label);
}
@@ -305,5 +390,4 @@
new Rect(0, 0, mImageView.getWidth(), mImageView.getHeight())));
});
}
-
}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuView.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuView.java
index 55f3981..e85bd88 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuView.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuView.java
@@ -544,9 +544,8 @@
final int currentX = (int) event.getX();
final int currentY = (int) event.getY();
- final int menuHalfWidth = getLayoutWidth() / 2;
final Rect touchDelegateBounds =
- new Rect(mMargin, mMargin, mMargin + menuHalfWidth, mMargin + getLayoutHeight());
+ new Rect(mMargin, mMargin, mMargin + getLayoutWidth(), mMargin + getLayoutHeight());
if (action == MotionEvent.ACTION_DOWN
&& touchDelegateBounds.contains(currentX, currentY)) {
mIsDownInEnlargedTouchArea = true;
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/BaseTooltipView.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/BaseTooltipView.java
index 1abf559..3085854 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/BaseTooltipView.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/BaseTooltipView.java
@@ -77,7 +77,6 @@
mAnchorView = anchorView;
mCurrentLayoutParams = createDefaultLayoutParams();
- updateDimensions();
initViews();
}
@@ -85,14 +84,8 @@
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
- updateDimensions();
- updateTextView();
-
mAnchorView.onConfigurationChanged(newConfig);
- final Rect anchorViewLocation = mAnchorView.getWindowLocationOnScreen();
- updateArrowWith(anchorViewLocation);
- updateWidthWith(anchorViewLocation);
- updateLocationWith(anchorViewLocation);
+ updateTooltipView();
mWindowManager.updateViewLayout(this, mCurrentLayoutParams);
}
@@ -129,10 +122,7 @@
}
mIsShowing = true;
- final Rect anchorViewLocation = mAnchorView.getWindowLocationOnScreen();
- updateArrowWith(anchorViewLocation);
- updateWidthWith(anchorViewLocation);
- updateLocationWith(anchorViewLocation);
+ updateTooltipView();
mWindowManager.addView(this, mCurrentLayoutParams);
}
@@ -207,6 +197,16 @@
R.dimen.accessibility_floating_tooltip_text_corner_radius);
}
+ private void updateTooltipView() {
+ updateDimensions();
+ updateTextView();
+
+ final Rect anchorViewLocation = mAnchorView.getWindowLocationOnScreen();
+ updateArrowWith(anchorViewLocation);
+ updateWidthWith(anchorViewLocation);
+ updateLocationWith(anchorViewLocation);
+ }
+
private void updateTextView() {
mTextView.setTextSize(COMPLEX_UNIT_PX, mFontSize);
mTextView.setPadding(mTextViewPadding, mTextViewPadding, mTextViewPadding,
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index e8300b9..3075617 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -630,6 +630,14 @@
animation.init();
mView.setAnimationViewController(animation);
+ // This view overlaps the sensor area, so prevent it from being selectable
+ // during a11y.
+ if (reason == IUdfpsOverlayController.REASON_ENROLL_FIND_SENSOR
+ || reason == IUdfpsOverlayController.REASON_ENROLL_ENROLLING) {
+ mView.setImportantForAccessibility(
+ View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
+ }
+
mWindowManager.addView(mView, computeLayoutParams(animation));
mAccessibilityManager.addTouchExplorationStateChangeListener(
mTouchExplorationStateChangeListener);
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollDrawable.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollDrawable.java
index 2c48d0a..83ae865 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollDrawable.java
@@ -16,6 +16,8 @@
package com.android.systemui.biometrics;
+import android.animation.AnimatorSet;
+import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
@@ -24,6 +26,9 @@
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import android.os.Looper;
+import android.view.animation.AccelerateDecelerateInterpolator;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -38,17 +43,33 @@
static final float PROGRESS_BAR_RADIUS = 360.f;
+ private static final long ANIM_DURATION = 800;
+ // 1 + SCALE_MAX is the maximum that the moving target will animate to
+ private static final float SCALE_MAX = 0.25f;
+
@NonNull private final Drawable mMovingTargetFpIcon;
@NonNull private final Paint mSensorOutlinePaint;
@NonNull private final Paint mBlueFill;
@NonNull private final Paint mBlueStroke;
+ @NonNull private final Handler mHandler;
@Nullable private RectF mSensorRect;
@Nullable private UdfpsEnrollHelper mEnrollHelper;
+ // Moving target animator set
+ @Nullable AnimatorSet mAnimatorSet;
+ // Moving target location
+ float mCurrentX;
+ float mCurrentY;
+ // Moving target size
+ float mCurrentScale = 1.f;
+
+
UdfpsEnrollDrawable(@NonNull Context context) {
super(context);
+ mHandler = new Handler(Looper.getMainLooper());
+
mSensorOutlinePaint = new Paint(0 /* flags */);
mSensorOutlinePaint.setAntiAlias(true);
mSensorOutlinePaint.setColor(mContext.getColor(R.color.udfps_enroll_icon));
@@ -90,6 +111,46 @@
invalidateSelf();
}
+ void onEnrollmentProgress(int remaining, int totalSteps) {
+ if (mEnrollHelper.isCenterEnrollmentComplete()) {
+ mHandler.post(() -> {
+ if (mAnimatorSet != null && mAnimatorSet.isRunning()) {
+ mAnimatorSet.end();
+ }
+
+ final PointF point = mEnrollHelper.getNextGuidedEnrollmentPoint();
+
+ final ValueAnimator x = ValueAnimator.ofFloat(mCurrentX, point.x);
+ x.addUpdateListener(animation -> {
+ mCurrentX = (float) animation.getAnimatedValue();
+ invalidateSelf();
+ });
+
+ final ValueAnimator y = ValueAnimator.ofFloat(mCurrentY, point.y);
+ y.addUpdateListener(animation -> {
+ mCurrentY = (float) animation.getAnimatedValue();
+ invalidateSelf();
+ });
+
+ final ValueAnimator scale = ValueAnimator.ofFloat(0, (float) Math.PI);
+ scale.setDuration(ANIM_DURATION);
+ scale.addUpdateListener(animation -> {
+ // Grow then shrink
+ mCurrentScale = 1 +
+ SCALE_MAX * (float) Math.sin((float) animation.getAnimatedValue());
+ invalidateSelf();
+ });
+
+ mAnimatorSet = new AnimatorSet();
+
+ mAnimatorSet.setInterpolator(new AccelerateDecelerateInterpolator());
+ mAnimatorSet.setDuration(ANIM_DURATION);
+ mAnimatorSet.playTogether(x, y, scale);
+ mAnimatorSet.start();
+ });
+ }
+ }
+
@Override
public void draw(@NonNull Canvas canvas) {
if (isIlluminationShowing()) {
@@ -98,13 +159,12 @@
// Draw moving target
if (mEnrollHelper.isCenterEnrollmentComplete()) {
- mFingerprintDrawable.setAlpha(mAlpha == 255 ? 64 : mAlpha);
- mSensorOutlinePaint.setAlpha(mAlpha == 255 ? 64 : mAlpha);
-
canvas.save();
- final PointF point = mEnrollHelper.getNextGuidedEnrollmentPoint();
- canvas.translate(point.x, point.y);
+ canvas.translate(mCurrentX, mCurrentY);
+
if (mSensorRect != null) {
+ canvas.scale(mCurrentScale, mCurrentScale,
+ mSensorRect.centerX(), mSensorRect.centerY());
canvas.drawOval(mSensorRect, mBlueFill);
canvas.drawOval(mSensorRect, mBlueStroke);
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollHelper.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollHelper.java
index 521c495..470fb8c 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollHelper.java
@@ -26,6 +26,7 @@
import android.provider.Settings;
import android.util.Log;
import android.util.TypedValue;
+import android.view.accessibility.AccessibilityManager;
import java.util.ArrayList;
import java.util.List;
@@ -53,6 +54,7 @@
@NonNull private final Context mContext;
// IUdfpsOverlayController reason
private final int mEnrollReason;
+ private final boolean mAccessibilityEnabled;
@NonNull private final List<PointF> mGuidedEnrollmentPoints;
private int mTotalSteps = -1;
@@ -67,6 +69,10 @@
public UdfpsEnrollHelper(@NonNull Context context, int reason) {
mContext = context;
mEnrollReason = reason;
+
+ final AccessibilityManager am = context.getSystemService(AccessibilityManager.class);
+ mAccessibilityEnabled = am.isEnabled();
+
mGuidedEnrollmentPoints = new ArrayList<>();
// Number of pixels per mm
@@ -148,6 +154,8 @@
boolean isCenterEnrollmentComplete() {
if (mTotalSteps == -1 || mRemainingSteps == -1) {
return false;
+ } else if (mAccessibilityEnabled) {
+ return false;
}
final int stepsEnrolled = mTotalSteps - mRemainingSteps;
return stepsEnrolled >= NUM_CENTER_TOUCHES;
@@ -155,6 +163,10 @@
@NonNull
PointF getNextGuidedEnrollmentPoint() {
+ if (mAccessibilityEnabled) {
+ return new PointF(0f, 0f);
+ }
+
float scale = SCALE;
if (Build.IS_ENG || Build.IS_USERDEBUG) {
scale = Settings.Secure.getFloatForUser(mContext.getContentResolver(),
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollView.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollView.java
index 75e8638..3bf1864 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollView.java
@@ -60,4 +60,8 @@
void setEnrollHelper(UdfpsEnrollHelper enrollHelper) {
mFingerprintDrawable.setEnrollHelper(enrollHelper);
}
+
+ void onEnrollmentProgress(int remaining, int totalSteps) {
+ mFingerprintDrawable.onEnrollmentProgress(remaining, totalSteps);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollViewController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollViewController.java
index 1ebbfbf..c1f3fe0 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollViewController.java
@@ -94,6 +94,7 @@
* Math.max(0, totalSteps + 1 - remaining) / (totalSteps + 1);
mProgressBar.setProgress(interpolatedProgress, true);
+ mView.onEnrollmentProgress(remaining, totalSteps);
}
};
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardDrawable.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardDrawable.java
index 6f7e6c3..8894093 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardDrawable.java
@@ -69,7 +69,8 @@
mHintAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
mHintAnimator.addUpdateListener(anim -> setStrokeWidth((float) anim.getAnimatedValue()));
- mLockScreenColor = Utils.getColorAttrDefaultColor(mContext, R.attr.wallpaperTextColor);
+ mLockScreenColor = Utils.getColorAttrDefaultColor(mContext,
+ R.attr.wallpaperTextColorAccent);
mAmbientDisplayColor = Color.WHITE;
updateIcon();
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java
index 52576a7..804e2ab 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java
@@ -148,7 +148,7 @@
/**
* Animates in the bg protection circle behind the fp icon to highlight the icon.
*/
- void animateUdfpsBouncer() {
+ void animateUdfpsBouncer(Runnable onEndAnimation) {
if (mBgProtection.getVisibility() == View.VISIBLE && mBgProtection.getAlpha() == 1f) {
// already fully highlighted, don't re-animate
return;
@@ -186,6 +186,14 @@
ObjectAnimator.ofFloat(mBgProtection, View.SCALE_X, 0f, 1f),
ObjectAnimator.ofFloat(mBgProtection, View.SCALE_Y, 0f, 1f),
fpIconAnim);
+ mAnimatorSet.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (onEndAnimation != null) {
+ onEndAnimation.run();
+ }
+ }
+ });
mAnimatorSet.start();
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
index a0ac2dc..78588b2 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
@@ -129,6 +129,7 @@
mStatusBarStateController.removeCallback(mStateListener);
mKeyguardViewManager.setAlternateAuthInterceptor(null);
mTransitioningFromHome = false;
+ mKeyguardUpdateMonitor.requestFaceAuthOnOccludingApp(false);
if (mCancelRunnable != null) {
mCancelRunnable.run();
@@ -165,11 +166,13 @@
mShowingUdfpsBouncer = show;
updatePauseAuth();
if (mShowingUdfpsBouncer) {
- mView.animateUdfpsBouncer();
+ mView.animateUdfpsBouncer(() ->
+ mKeyguardUpdateMonitor.requestFaceAuthOnOccludingApp(true));
mView.announceForAccessibility(mView.getContext().getString(
R.string.accessibility_fingerprint_bouncer));
} else {
mView.animateAwayUdfpsBouncer(null);
+ mKeyguardUpdateMonitor.requestFaceAuthOnOccludingApp(false);
}
return true;
}
@@ -269,7 +272,7 @@
private void updateAlpha() {
// fade icon on transition to showing bouncer
int alpha = mShowingUdfpsBouncer ? 255
- : Math.abs((int) MathUtils.map(.4f, 0f, .7f, 255f,
+ : Math.abs((int) MathUtils.constrainedMap(0f, 255f, .4f, .7f,
mInputBouncerHiddenAmount));
mView.setUnpausedAlpha(alpha);
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java
index 0f202b0..9697369 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java
@@ -257,7 +257,9 @@
@Override
public void onTouchEvent(MotionEvent ev) {
- if (!mKeyguardStateController.isShowing() || mStatusBarStateController.isDozing()) {
+ if (!mKeyguardStateController.isShowing()
+ || (mStatusBarStateController.isDozing()
+ && !mStatusBarStateController.isPulsing())) {
avoidGesture();
return;
}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsComponent.kt b/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsComponent.kt
index 5557c86..469e60a 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsComponent.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsComponent.kt
@@ -51,7 +51,6 @@
private val userTracker: UserTracker,
private val secureSettings: SecureSettings
) {
-
private val contentResolver: ContentResolver
get() = context.contentResolver
@@ -66,7 +65,7 @@
init {
if (featureEnabled) {
secureSettings.registerContentObserver(
- Settings.Secure.getUriFor(Settings.Secure.POWER_MENU_LOCKED_SHOW_CONTENT),
+ Settings.Secure.getUriFor(Settings.Secure.LOCKSCREEN_SHOW_CONTROLS),
false, /* notifyForDescendants */
showWhileLockedObserver
)
@@ -116,7 +115,7 @@
private fun updateShowWhileLocked() {
canShowWhileLockedSetting = secureSettings.getInt(
- Settings.Secure.POWER_MENU_LOCKED_SHOW_CONTENT, 0) != 0
+ Settings.Secure.LOCKSCREEN_SHOW_CONTROLS, 0) != 0
}
enum class Visibility {
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsProviderSelectorActivity.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsProviderSelectorActivity.kt
index cba3dab..8ad5099 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsProviderSelectorActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsProviderSelectorActivity.kt
@@ -55,8 +55,9 @@
companion object {
private const val TAG = "ControlsProviderSelectorActivity"
+ const val BACK_SHOULD_EXIT = "back_should_exit"
}
-
+ private var backShouldExit = false
private lateinit var recyclerView: RecyclerView
private val currentUserTracker = object : CurrentUserTracker(broadcastDispatcher) {
private val startingUser = listingController.currentUserId
@@ -102,13 +103,17 @@
}
}
requireViewById<View>(R.id.done).visibility = View.GONE
+
+ backShouldExit = intent.getBooleanExtra(BACK_SHOULD_EXIT, false)
}
override fun onBackPressed() {
- val i = Intent().apply {
- component = ComponentName(applicationContext, ControlsActivity::class.java)
+ if (!backShouldExit) {
+ val i = Intent().apply {
+ component = ComponentName(applicationContext, ControlsActivity::class.java)
+ }
+ startActivity(i, ActivityOptions.makeSceneTransitionAnimation(this).toBundle())
}
- startActivity(i, ActivityOptions.makeSceneTransitionAnimation(this).toBundle())
animateExitAndFinish()
}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt
index 43607dd..47e749c 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt
@@ -46,6 +46,8 @@
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
+import androidx.annotation.ColorInt
+import androidx.annotation.VisibleForTesting
import com.android.internal.graphics.ColorUtils
import com.android.systemui.R
import com.android.systemui.animation.Interpolators
@@ -313,7 +315,8 @@
@ColorRes bgColor: Int
) {
val bg = context.resources.getColor(R.color.control_default_background, context.theme)
- var (newClipColor, newAlpha) = if (enabled) {
+
+ val (newClipColor, newAlpha) = if (enabled) {
// allow color overrides for the enabled state only
val color = cws.control?.getCustomColor()?.let {
val state = intArrayOf(android.R.attr.state_enabled)
@@ -326,58 +329,87 @@
ALPHA_DISABLED
)
}
+ val newBaseColor = if (behavior is ToggleRangeBehavior) {
+ ColorUtils.blendARGB(bg, newClipColor, toggleBackgroundIntensity)
+ } else {
+ bg
+ }
- clipLayer.getDrawable().apply {
+ clipLayer.drawable?.apply {
clipLayer.alpha = ALPHA_DISABLED
-
- val newBaseColor = if (behavior is ToggleRangeBehavior) {
- ColorUtils.blendARGB(bg, newClipColor, toggleBackgroundIntensity)
- } else {
- bg
- }
stateAnimator?.cancel()
if (animated) {
- val oldColor = if (this is GradientDrawable) {
- this.color?.defaultColor ?: newClipColor
- } else {
- newClipColor
- }
- val oldBaseColor = baseLayer.color?.defaultColor ?: newBaseColor
- val oldAlpha = layout.alpha
-
- // Animate both alpha and background colors. Only animate colors for
- // GradientDrawables and not static images as used for the ThumbnailTemplate.
- stateAnimator = ValueAnimator.ofInt(clipLayer.alpha, newAlpha).apply {
- addUpdateListener {
- alpha = it.animatedValue as Int
- if (this is GradientDrawable) {
- this.setColor(ColorUtils.blendARGB(oldColor, newClipColor,
- it.animatedFraction))
- }
- baseLayer.setColor(ColorUtils.blendARGB(oldBaseColor, newBaseColor,
- it.animatedFraction))
- layout.alpha = MathUtils.lerp(oldAlpha, 1f, it.animatedFraction)
- }
- addListener(object : AnimatorListenerAdapter() {
- override fun onAnimationEnd(animation: Animator?) {
- stateAnimator = null
- }
- })
- duration = STATE_ANIMATION_DURATION
- interpolator = Interpolators.CONTROL_STATE
- start()
- }
+ startBackgroundAnimation(this, newAlpha, newClipColor, newBaseColor)
} else {
- alpha = newAlpha
- if (this is GradientDrawable) {
- this.setColor(newClipColor)
- }
- baseLayer.setColor(newBaseColor)
- layout.alpha = 1f
+ applyBackgroundChange(
+ this, newAlpha, newClipColor, newBaseColor, newLayoutAlpha = 1f
+ )
}
}
}
+ private fun startBackgroundAnimation(
+ clipDrawable: Drawable,
+ newAlpha: Int,
+ @ColorInt newClipColor: Int,
+ @ColorInt newBaseColor: Int
+ ) {
+ val oldClipColor = if (clipDrawable is GradientDrawable) {
+ clipDrawable.color?.defaultColor ?: newClipColor
+ } else {
+ newClipColor
+ }
+ val oldBaseColor = baseLayer.color?.defaultColor ?: newBaseColor
+ val oldAlpha = layout.alpha
+
+ stateAnimator = ValueAnimator.ofInt(clipLayer.alpha, newAlpha).apply {
+ addUpdateListener {
+ val updatedAlpha = it.animatedValue as Int
+ val updatedClipColor = ColorUtils.blendARGB(oldClipColor, newClipColor,
+ it.animatedFraction)
+ val updatedBaseColor = ColorUtils.blendARGB(oldBaseColor, newBaseColor,
+ it.animatedFraction)
+ val updatedLayoutAlpha = MathUtils.lerp(oldAlpha, 1f, it.animatedFraction)
+ applyBackgroundChange(
+ clipDrawable,
+ updatedAlpha,
+ updatedClipColor,
+ updatedBaseColor,
+ updatedLayoutAlpha
+ )
+ }
+ addListener(object : AnimatorListenerAdapter() {
+ override fun onAnimationEnd(animation: Animator?) {
+ stateAnimator = null
+ }
+ })
+ duration = STATE_ANIMATION_DURATION
+ interpolator = Interpolators.CONTROL_STATE
+ start()
+ }
+ }
+
+ /**
+ * Applies a change in background.
+ *
+ * Updates both alpha and background colors. Only updates colors for GradientDrawables and not
+ * static images as used for the ThumbnailTemplate.
+ */
+ private fun applyBackgroundChange(
+ clipDrawable: Drawable,
+ newAlpha: Int,
+ @ColorInt newClipColor: Int,
+ @ColorInt newBaseColor: Int,
+ newLayoutAlpha: Float
+ ) {
+ clipDrawable.alpha = newAlpha
+ if (clipDrawable is GradientDrawable) {
+ clipDrawable.setColor(newClipColor)
+ }
+ baseLayer.setColor(newBaseColor)
+ layout.alpha = newLayoutAlpha
+ }
+
private fun animateStatusChange(animated: Boolean, statusRowUpdater: () -> Unit) {
statusAnimator?.cancel()
@@ -423,7 +455,8 @@
}
}
- private fun updateStatusRow(
+ @VisibleForTesting
+ internal fun updateStatusRow(
enabled: Boolean,
text: CharSequence,
drawable: Drawable,
@@ -438,11 +471,8 @@
status.setTextColor(color)
control?.getCustomIcon()?.let {
- // do not tint custom icons, assume the intended icon color is correct
- if (icon.imageTintList != null) {
- icon.imageTintList = null
- }
icon.setImageIcon(it)
+ icon.imageTintList = it.tintList
} ?: run {
if (drawable is StateListDrawable) {
// Only reset the drawable if it is a different resource, as it will interfere
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 26be987..c322f45 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
@@ -217,22 +217,8 @@
}
private fun showInitialSetupView(items: List<SelectionItem>) {
- val inflater = LayoutInflater.from(context)
- inflater.inflate(R.layout.controls_no_favorites, parent, true)
-
- val viewGroup = parent.requireViewById(R.id.controls_no_favorites_group) as ViewGroup
- viewGroup.setOnClickListener { _: View -> startProviderSelectorActivity() }
-
- val subtitle = parent.requireViewById<TextView>(R.id.controls_subtitle)
- subtitle.setText(context.resources.getString(R.string.quick_controls_subtitle))
-
- val iconRowGroup = parent.requireViewById(R.id.controls_icon_row) as ViewGroup
- items.forEach {
- val imageView = inflater.inflate(R.layout.controls_icon, viewGroup, false) as ImageView
- imageView.setContentDescription(it.getTitle())
- imageView.setImageDrawable(it.icon)
- iconRowGroup.addView(imageView)
- }
+ startProviderSelectorActivity()
+ onDismiss.run()
}
private fun startFavoritingActivity(si: StructureInfo) {
@@ -261,7 +247,9 @@
}
private fun startProviderSelectorActivity() {
- startActivity(Intent(activityContext, ControlsProviderSelectorActivity::class.java))
+ val i = Intent(activityContext, ControlsProviderSelectorActivity::class.java)
+ i.putExtra(ControlsProviderSelectorActivity.BACK_SHOULD_EXIT, true)
+ startActivity(i)
}
private fun startActivity(intent: Intent) {
diff --git a/packages/SystemUI/src/com/android/systemui/media/KeyguardMediaController.kt b/packages/SystemUI/src/com/android/systemui/media/KeyguardMediaController.kt
index b668e88..241c2a9 100644
--- a/packages/SystemUI/src/com/android/systemui/media/KeyguardMediaController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/KeyguardMediaController.kt
@@ -64,6 +64,12 @@
mediaHost.init(MediaHierarchyManager.LOCATION_LOCKSCREEN)
}
+ /**
+ * Is the media player visible?
+ */
+ var visible = false
+ private set
+
var visibilityChangedListener: ((Boolean) -> Unit)? = null
/**
@@ -106,11 +112,11 @@
val keyguardOrUserSwitcher = (statusBarStateController.state == StatusBarState.KEYGUARD ||
statusBarStateController.state == StatusBarState.FULLSCREEN_USER_SWITCHER)
// mediaHost.visible required for proper animations handling
- val shouldBeVisible = mediaHost.visible &&
+ visible = mediaHost.visible &&
!bypassController.bypassEnabled &&
keyguardOrUserSwitcher &&
notifLockscreenUserManager.shouldShowLockscreenNotifications()
- if (shouldBeVisible) {
+ if (visible) {
showMediaPlayer()
} else {
hideMediaPlayer()
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
index ef53233..a1c06fc 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
@@ -3,6 +3,7 @@
import android.app.smartspace.SmartspaceTarget
import android.content.Context
import android.content.Intent
+import android.content.res.ColorStateList
import android.content.res.Configuration
import android.provider.Settings.ACTION_MEDIA_CONTROLS_SETTINGS
import android.util.Log
@@ -207,9 +208,13 @@
}
}
- override fun onSmartspaceMediaDataLoaded(key: String, data: SmartspaceTarget) {
+ override fun onSmartspaceMediaDataLoaded(
+ key: String,
+ data: SmartspaceTarget,
+ shouldPrioritize: Boolean
+ ) {
Log.d(TAG, "My Smartspace media update is here")
- addSmartspaceMediaRecommendations(key, data)
+ addSmartspaceMediaRecommendations(key, data, shouldPrioritize)
MediaPlayerData.getMediaPlayer(key, null)?.let {
logSmartspaceCardReported(759, // SMARTSPACE_CARD_RECEIVED
it.mInstanceId,
@@ -326,7 +331,11 @@
return existingPlayer == null
}
- private fun addSmartspaceMediaRecommendations(key: String, data: SmartspaceTarget) {
+ private fun addSmartspaceMediaRecommendations(
+ key: String,
+ data: SmartspaceTarget,
+ shouldPrioritize: Boolean
+ ) {
Log.d(TAG, "Updating smartspace target in carousel")
if (MediaPlayerData.getMediaPlayer(key, null) != null) {
Log.w(TAG, "Skip adding smartspace target in carousel")
@@ -341,7 +350,7 @@
ViewGroup.LayoutParams.WRAP_CONTENT)
newRecs.recommendationViewHolder?.recommendations?.setLayoutParams(lp)
newRecs.bindRecommendation(data, bgColor)
- MediaPlayerData.addMediaRecommendation(key, newRecs)
+ MediaPlayerData.addMediaRecommendation(key, newRecs, shouldPrioritize)
updatePlayerToState(newRecs, noAnimation = true)
reorderAllPlayers()
updatePageIndicator()
@@ -380,6 +389,7 @@
private fun recreatePlayers() {
bgColor = getBackgroundColor()
+ pageIndicator.tintList = ColorStateList.valueOf(getForegroundColor())
MediaPlayerData.mediaData().forEach { (key, data) ->
removePlayer(key, dismissMediaData = false)
@@ -391,6 +401,10 @@
return context.getColor(android.R.color.system_accent2_50)
}
+ private fun getForegroundColor(): Int {
+ return context.getColor(android.R.color.system_accent2_900)
+ }
+
private fun updatePageIndicator() {
val numPages = mediaContent.getChildCount()
pageIndicator.setNumPages(numPages)
@@ -665,17 +679,19 @@
internal object MediaPlayerData {
private val EMPTY = MediaData(-1, false, 0, null, null, null, null, null,
emptyList(), emptyList(), "INVALID", null, null, null, true, null)
+ // Whether should prioritize Smartspace card.
+ private var shouldPrioritizeSs: Boolean = false
data class MediaSortKey(
- // Is Smartspace media recommendation. When the Smartspace media is present, it should
- // always be the first card in carousel.
+ // Whether the item represents a Smartspace media recommendation.
val isSsMediaRec: Boolean,
val data: MediaData,
val updateTime: Long = 0
)
private val comparator =
- compareByDescending<MediaSortKey> { it.isSsMediaRec }
+ compareByDescending<MediaSortKey>
+ { if (shouldPrioritizeSs) it.isSsMediaRec else !it.isSsMediaRec }
.thenByDescending { it.data.isPlaying }
.thenByDescending { it.data.isLocalSession }
.thenByDescending { !it.data.resumption }
@@ -691,7 +707,8 @@
mediaPlayers.put(sortKey, player)
}
- fun addMediaRecommendation(key: String, player: MediaControlPanel) {
+ fun addMediaRecommendation(key: String, player: MediaControlPanel, shouldPrioritize: Boolean) {
+ shouldPrioritizeSs = shouldPrioritize
removeMediaPlayer(key)
val sortKey = MediaSortKey(isSsMediaRec = true, EMPTY, System.currentTimeMillis())
mediaData.put(key, sortKey)
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
index c608dc7..e213dfe 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
@@ -45,6 +45,7 @@
import androidx.annotation.UiThread;
import androidx.constraintlayout.widget.ConstraintSet;
+import com.android.settingslib.Utils;
import com.android.settingslib.widget.AdaptiveIcon;
import com.android.systemui.R;
import com.android.systemui.animation.ActivityLaunchAnimator;
@@ -303,11 +304,23 @@
}
// App icon
- ImageView appIcon = mPlayerViewHolder.getAppIcon();
- if (data.getAppIcon() != null) {
- appIcon.setImageIcon(data.getAppIcon());
+ ImageView appIconView = mPlayerViewHolder.getAppIcon();
+ appIconView.clearColorFilter();
+ if (data.getAppIcon() != null && !data.getResumption()) {
+ appIconView.setImageIcon(data.getAppIcon());
+ int color = Utils.getColorAttrDefaultColor(mContext,
+ com.android.internal.R.attr.colorAccentTertiary);
+ appIconView.setColorFilter(color);
} else {
- appIcon.setImageResource(R.drawable.ic_music_note);
+ appIconView.setColorFilter(getGrayscaleFilter());
+ try {
+ Drawable icon = mContext.getPackageManager().getApplicationIcon(
+ data.getPackageName());
+ appIconView.setImageDrawable(icon);
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.w(TAG, "Cannot find icon for package " + data.getPackageName(), e);
+ appIconView.setImageResource(R.drawable.ic_music_note);
+ }
}
// Song name
@@ -400,7 +413,7 @@
setVisibleAndAlpha(collapsedSet, ACTION_IDS[i], false /*visible */);
setVisibleAndAlpha(expandedSet, ACTION_IDS[i], false /* visible */);
}
- // If no expanded buttons, set the first view as INVISIBLE so z remains constant
+ // If no actions, set the first view as INVISIBLE so expanded height remains constant
if (actionIcons.size() == 0) {
expandedSet.setVisibility(ACTION_IDS[0], ConstraintSet.INVISIBLE);
}
@@ -514,9 +527,9 @@
// Get the logo from app's package name when applicable.
String packageName = extras.getString(EXTRAS_MEDIA_SOURCE_PACKAGE_NAME);
try {
- Drawable drawable = mContext.getPackageManager().getApplicationIcon(
+ icon = mContext.getPackageManager().getApplicationIcon(
packageName);
- icon = convertToGrayscale(drawable);
+ icon.setColorFilter(getGrayscaleFilter());
} catch (PackageManager.NameNotFoundException e) {
Log.w(TAG, "No media source icon can be fetched via package name", e);
}
@@ -646,13 +659,10 @@
return (state.getState() == PlaybackState.STATE_PLAYING);
}
- /** Convert the pass-in source drawable to a grayscale one. */
- private Drawable convertToGrayscale(Drawable drawable) {
+ private ColorMatrixColorFilter getGrayscaleFilter() {
ColorMatrix matrix = new ColorMatrix();
matrix.setSaturation(0);
- ColorMatrixColorFilter filter = new ColorMatrixColorFilter(matrix);
- drawable.setColorFilter(filter);
- return drawable;
+ return new ColorMatrixColorFilter(matrix);
}
private void setVisibleAndAlpha(ConstraintSet set, int actionId, boolean visible) {
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataCombineLatest.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataCombineLatest.kt
index 2c094b8..87af9e0 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaDataCombineLatest.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataCombineLatest.kt
@@ -38,7 +38,11 @@
}
}
- override fun onSmartspaceMediaDataLoaded(key: String, data: SmartspaceTarget) {
+ override fun onSmartspaceMediaDataLoaded(
+ key: String,
+ data: SmartspaceTarget,
+ shouldPrioritize: Boolean
+ ) {
listeners.toSet().forEach { it.onSmartspaceMediaDataLoaded(key, data) }
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt
index e5c15107..3deb5d1 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt
@@ -26,9 +26,11 @@
import com.android.systemui.settings.CurrentUserTracker
import com.android.systemui.statusbar.NotificationLockscreenUserManager
import com.android.systemui.util.time.SystemClock
+import java.util.SortedMap
import java.util.concurrent.Executor
import java.util.concurrent.TimeUnit
import javax.inject.Inject
+import kotlin.collections.LinkedHashMap
private const val TAG = "MediaDataFilter"
private const val DEBUG = true
@@ -39,7 +41,7 @@
*/
@VisibleForTesting
internal val SMARTSPACE_MAX_AGE = SystemProperties
- .getLong("debug.sysui.smartspace_max_age", TimeUnit.HOURS.toMillis(3))
+ .getLong("debug.sysui.smartspace_max_age", TimeUnit.MINUTES.toMillis(30))
/**
* Filters data updates from [MediaDataCombineLatest] based on the current user ID, and handles user
@@ -65,7 +67,8 @@
private val allEntries: LinkedHashMap<String, MediaData> = LinkedHashMap()
// The filtered userEntries, which will be a subset of all userEntries in MediaDataManager
private val userEntries: LinkedHashMap<String, MediaData> = LinkedHashMap()
- private var hasSmartspace: Boolean = false
+ var hasSmartspace: Boolean = false
+ private set
private var reactivatedKey: String? = null
init {
@@ -99,39 +102,39 @@
}
}
- override fun onSmartspaceMediaDataLoaded(key: String, data: SmartspaceTarget) {
+ override fun onSmartspaceMediaDataLoaded(
+ key: String,
+ data: SmartspaceTarget,
+ shouldPrioritize: Boolean
+ ) {
+ var shouldPrioritizeMutable = shouldPrioritize
hasSmartspace = true
// Before forwarding the smartspace target, first check if we have recently inactive media
- val now = systemClock.elapsedRealtime()
val sorted = userEntries.toSortedMap(compareBy {
userEntries.get(it)?.lastActive ?: -1
})
- if (sorted.size > 0) {
+ val timeSinceActive = timeSinceActiveForMostRecentMedia(sorted)
+ if (timeSinceActive < SMARTSPACE_MAX_AGE) {
val lastActiveKey = sorted.lastKey() // most recently active
- val timeSinceActive = sorted.get(lastActiveKey)?.let {
- now - it.lastActive
- } ?: Long.MAX_VALUE
- if (timeSinceActive < SMARTSPACE_MAX_AGE) {
- // Notify listeners to consider this media active
- Log.d(TAG, "reactivating $lastActiveKey instead of smartspace")
- reactivatedKey = lastActiveKey
- val mediaData = sorted.get(lastActiveKey)!!.copy(active = true)
- listeners.forEach {
- it.onMediaDataLoaded(lastActiveKey, lastActiveKey, mediaData)
- }
- return
+ // Notify listeners to consider this media active
+ Log.d(TAG, "reactivating $lastActiveKey instead of smartspace")
+ reactivatedKey = lastActiveKey
+ val mediaData = sorted.get(lastActiveKey)!!.copy(active = true)
+ listeners.forEach {
+ it.onMediaDataLoaded(lastActiveKey, lastActiveKey, mediaData)
}
+ } else {
+ // Mark to prioritize Smartspace card if no recent media.
+ shouldPrioritizeMutable = true
}
- // If no recent media, continue with smartspace update
+ // Only proceed with the Smartspace update if the recommendation is not empty.
if (isMediaRecommendationEmpty(data)) {
Log.d(TAG, "Empty media recommendations. Skip showing the card")
return
}
-
- // Proceed only if the Smartspace recommendation is not empty.
- listeners.forEach { it.onSmartspaceMediaDataLoaded(key, data) }
+ listeners.forEach { it.onSmartspaceMediaDataLoaded(key, data, shouldPrioritizeMutable) }
}
override fun onMediaDataRemoved(key: String) {
@@ -158,7 +161,6 @@
it.onMediaDataLoaded(lastActiveKey, lastActiveKey, mediaData)
}
}
- return
}
listeners.forEach { it.onSmartspaceMediaDataRemoved(key) }
@@ -230,4 +232,26 @@
val mediaRecommendationList: List<SmartspaceAction> = data.getIconGrid()
return mediaRecommendationList == null || mediaRecommendationList.isEmpty()
}
+
+ /**
+ * Return the time since last active for the most-recent media.
+ *
+ * @param sortedEntries userEntries sorted from the earliest to the most-recent.
+ *
+ * @return The duration in milliseconds from the most-recent media's last active timestamp to
+ * the present. MAX_VALUE will be returned if there is no media.
+ */
+ private fun timeSinceActiveForMostRecentMedia(
+ sortedEntries: SortedMap<String, MediaData>
+ ): Long {
+ if (sortedEntries.isEmpty()) {
+ return Long.MAX_VALUE
+ }
+
+ val now = systemClock.elapsedRealtime()
+ val lastActiveKey = sortedEntries.lastKey() // most recently active
+ return sortedEntries.get(lastActiveKey)?.let {
+ now - it.lastActive
+ } ?: Long.MAX_VALUE
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
index a45bd33..ffcec29 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
@@ -817,8 +817,17 @@
*/
fun onMediaDataLoaded(key: String, oldKey: String?, data: MediaData) {}
- /** Called whenever there's new Smartspace media data loaded. */
- fun onSmartspaceMediaDataLoaded(key: String, data: SmartspaceTarget) {}
+ /**
+ * Called whenever there's new Smartspace media data loaded.
+ *
+ * shouldPrioritize indicates the sorting priority of the Smartspace card. If true, it will
+ * be prioritized as the first card. Otherwise, it will show up as the last card as default.
+ */
+ fun onSmartspaceMediaDataLoaded(
+ key: String,
+ data: SmartspaceTarget,
+ shouldPrioritize: Boolean = false
+ ) {}
/**
* Called whenever a previously existing Media notification was removed
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt
index 60e832a..73dfe5e 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt
@@ -26,6 +26,7 @@
import android.view.View
import android.view.ViewGroup
import android.view.ViewGroupOverlay
+import com.android.systemui.R
import com.android.systemui.animation.Interpolators
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.WakefulnessLifecycle
@@ -35,6 +36,7 @@
import com.android.systemui.statusbar.SysuiStatusBarStateController
import com.android.systemui.statusbar.notification.stack.StackStateAnimator
import com.android.systemui.statusbar.phone.KeyguardBypassController
+import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.animation.UniqueObjectHostView
import javax.inject.Inject
@@ -74,6 +76,7 @@
private val bypassController: KeyguardBypassController,
private val mediaCarouselController: MediaCarouselController,
private val notifLockscreenUserManager: NotificationLockscreenUserManager,
+ configurationController: ConfigurationController,
wakefulnessLifecycle: WakefulnessLifecycle,
private val statusBarKeyguardViewManager: StatusBarKeyguardViewManager
) {
@@ -183,6 +186,58 @@
}
/**
+ * distance that the full shade transition takes in order for media to fully transition to the
+ * shade
+ */
+ private var distanceForFullShadeTransition = 0
+
+ /**
+ * Delay after which the media will start transitioning to the full shade on the lockscreen.
+ */
+ private var fullShadeTransitionDelay = 0
+
+ /**
+ * The amount of progress we are currently in if we're transitioning to the full shade.
+ * 0.0f means we're not transitioning yet, while 1 means we're all the way in the full
+ * shade.
+ */
+ private var fullShadeTransitionProgress = 0f
+ set(value) {
+ if (field == value) {
+ return
+ }
+ field = value
+ if (bypassController.bypassEnabled) {
+ return
+ }
+ updateDesiredLocation()
+ if (value >= 0) {
+ updateTargetState()
+ applyTargetStateIfNotAnimating()
+ }
+ }
+
+ private val isTransitioningToFullShade: Boolean
+ get() = fullShadeTransitionProgress != 0f && !bypassController.bypassEnabled
+
+ /**
+ * Set the amount of pixels we have currently dragged down if we're transitioning to the full
+ * shade. 0.0f means we're not transitioning yet.
+ */
+ fun setTransitionToFullShadeAmount(value: Float) {
+ // If we're transitioning starting on the shade_locked, we don't want any delay and rather
+ // have it aligned with the rest of the animation
+ val delay = if (statusbarState == StatusBarState.KEYGUARD) {
+ fullShadeTransitionDelay
+ } else {
+ 0
+ }
+ val progress = MathUtils.saturate((value - delay) /
+ (distanceForFullShadeTransition - delay))
+ fullShadeTransitionProgress = Interpolators.FAST_OUT_SLOW_IN.getInterpolation(progress)
+ }
+
+ /**
* Is the shade currently collapsing from the expanded qs? If we're on the lockscreen and in qs,
* we wouldn't want to transition in that case.
*/
@@ -242,6 +297,12 @@
}
init {
+ updateConfiguration()
+ configurationController.addCallback(object : ConfigurationController.ConfigurationListener {
+ override fun onDensityOrFontScaleChanged() {
+ updateConfiguration()
+ }
+ })
statusBarStateController.addCallback(object : StatusBarStateController.StateListener {
override fun onStatePreChange(oldState: Int, newState: Int) {
// We're updating the location before the state change happens, since we want the
@@ -312,6 +373,13 @@
})
}
+ private fun updateConfiguration() {
+ distanceForFullShadeTransition = context.resources.getDimensionPixelSize(
+ R.dimen.lockscreen_shade_qs_transition_distance)
+ fullShadeTransitionDelay = context.resources.getDimensionPixelSize(
+ R.dimen.lockscreen_shade_media_transition_start_delay)
+ }
+
/**
* Register a media host and create a view can be attached to a view hierarchy
* and where the players will be placed in when the host is the currently desired state.
@@ -546,6 +614,9 @@
if (progress >= 0) {
return progress
}
+ if (isTransitioningToFullShade) {
+ return fullShadeTransitionProgress
+ }
return -1.0f
}
@@ -643,6 +714,7 @@
val location = when {
qsExpansion > 0.0f && !onLockscreen -> LOCATION_QS
qsExpansion > 0.4f && onLockscreen -> LOCATION_QS
+ onLockscreen && isTransitioningToFullShade -> LOCATION_QQS
onLockscreen && allowedOnLockscreen -> LOCATION_LOCKSCREEN
else -> LOCATION_QQS
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt b/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt
index 28e4640..7402107 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt
@@ -56,7 +56,11 @@
updateViewVisibility()
}
- override fun onSmartspaceMediaDataLoaded(key: String, data: SmartspaceTarget) {
+ override fun onSmartspaceMediaDataLoaded(
+ key: String,
+ data: SmartspaceTarget,
+ shouldPrioritize: Boolean
+ ) {
updateViewVisibility()
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaSessionBasedFilter.kt b/packages/SystemUI/src/com/android/systemui/media/MediaSessionBasedFilter.kt
index d973478..3e5e8248 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaSessionBasedFilter.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaSessionBasedFilter.kt
@@ -135,7 +135,11 @@
}
}
- override fun onSmartspaceMediaDataLoaded(key: String, data: SmartspaceTarget) {
+ override fun onSmartspaceMediaDataLoaded(
+ key: String,
+ data: SmartspaceTarget,
+ shouldPrioritize: Boolean
+ ) {
backgroundExecutor.execute {
dispatchSmartspaceMediaDataLoaded(key, data)
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
index c6373f5..bcef43c 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
@@ -24,6 +24,7 @@
import android.graphics.PorterDuffColorFilter;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Icon;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
@@ -41,6 +42,7 @@
import com.android.settingslib.bluetooth.BluetoothUtils;
import com.android.settingslib.media.MediaDevice;
+import com.android.settingslib.utils.ThreadUtils;
import com.android.systemui.R;
import com.android.systemui.animation.Interpolators;
@@ -116,6 +118,7 @@
final View mDivider;
final View mBottomDivider;
final CheckBox mCheckBox;
+ private String mDeviceId;
MediaDeviceBaseViewHolder(View view) {
super(view);
@@ -134,8 +137,17 @@
}
void onBind(MediaDevice device, boolean topMargin, boolean bottomMargin) {
- mTitleIcon.setImageIcon(mController.getDeviceIconCompat(device).toIcon(mContext));
- setMargin(topMargin, bottomMargin);
+ mDeviceId = device.getId();
+ ThreadUtils.postOnBackgroundThread(() -> {
+ Icon icon = mController.getDeviceIconCompat(device).toIcon(mContext);
+ ThreadUtils.postOnMainThread(() -> {
+ if (!TextUtils.equals(mDeviceId, device.getId())) {
+ return;
+ }
+ mTitleIcon.setImageIcon(icon);
+ setMargin(topMargin, bottomMargin);
+ });
+ });
}
void onBind(int customizedItem, boolean topMargin, boolean bottomMargin) {
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
index 4e41d75..04f5199 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
@@ -364,6 +364,11 @@
}
@Override
+ public void onHomeRotationEnabled(boolean enabled) {
+ mNavigationBarView.getRotationButtonController().setHomeRotationEnabled(enabled);
+ }
+
+ @Override
public void onOverviewShown(boolean fromHome) {
// If the overview has fixed orientation that may change display to natural rotation,
// we don't want the user rotation to be reset. So after user returns to application,
@@ -951,6 +956,7 @@
if (running) {
mNavbarOverlayController.setButtonState(/* visible */false, /* force */true);
}
+ mNavigationBarView.getRotationButtonController().setRecentsAnimationRunning(running);
}
/** Restores the appearance and the transient saved state to {@link NavigationBar}. */
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
index 9c3cb2e..ae9b598 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
@@ -184,6 +184,7 @@
mNavMode = mNavigationModeController.addListener(this);
mNavigationModeController.addListener(this);
mTaskbarDelegate = new TaskbarDelegate(mOverviewProxyService);
+ mIsTablet = isTablet(mContext.getResources().getConfiguration());
}
@Override
@@ -297,6 +298,10 @@
*/
public void createNavigationBars(final boolean includeDefaultDisplay,
RegisterStatusBarResult result) {
+ if (updateNavbarForTaskbar()) {
+ return;
+ }
+
Display[] displays = mDisplayManager.getDisplays();
for (Display display : displays) {
if (includeDefaultDisplay || display.getDisplayId() != DEFAULT_DISPLAY) {
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarOverlayController.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarOverlayController.java
index 40f908b..9f2fb50 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarOverlayController.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarOverlayController.java
@@ -17,6 +17,7 @@
package com.android.systemui.navigationbar;
import android.content.Context;
+import android.graphics.Rect;
import android.view.View;
import com.android.systemui.dagger.SysUISingleton;
@@ -47,7 +48,8 @@
/**
* Initialize the controller with visibility change callback.
*/
- public void init(Consumer<Boolean> visibilityChangeCallback) {}
+ public void init(Consumer<Boolean> visibilityChangeCallback,
+ Consumer<Rect> excludeBackRegionCallback) {}
/**
* Set whether the view can be shown.
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
index fcbd596..7af4853 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
@@ -323,10 +323,6 @@
mOverviewProxyService = Dependency.get(OverviewProxyService.class);
mRecentsOnboarding = new RecentsOnboarding(context, mOverviewProxyService);
- mNavBarOverlayController = Dependency.get(NavigationBarOverlayController.class);
- if (mNavBarOverlayController.isNavigationBarOverlayEnabled()) {
- mNavBarOverlayController.init(mNavbarOverlayVisibilityChangeCallback);
- }
mConfiguration = new Configuration();
mTmpLastConfiguration = new Configuration();
@@ -371,6 +367,12 @@
return isGesturalModeOnDefaultDisplay(getContext(), mNavBarMode);
}
});
+
+ mNavBarOverlayController = Dependency.get(NavigationBarOverlayController.class);
+ if (mNavBarOverlayController.isNavigationBarOverlayEnabled()) {
+ mNavBarOverlayController.init(mNavbarOverlayVisibilityChangeCallback,
+ mEdgeBackGestureHandler::updateNavigationBarOverlayExcludeRegion);
+ }
}
public void setAutoHideController(AutoHideController autoHideController) {
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/RotationButtonController.java b/packages/SystemUI/src/com/android/systemui/navigationbar/RotationButtonController.java
index ddf089b..649ac87 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/RotationButtonController.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/RotationButtonController.java
@@ -71,6 +71,8 @@
private final ViewRippler mViewRippler = new ViewRippler();
private RotationButton mRotationButton;
+ private boolean mIsRecentsAnimationRunning;
+ private boolean mHomeRotationEnabled;
private int mLastRotationSuggestion;
private boolean mPendingRotationSuggestion;
private boolean mHoveringRotationSuggestion;
@@ -92,7 +94,6 @@
() -> mPendingRotationSuggestion = false;
private Animator mRotateHideAnimator;
-
private final Stub mRotationWatcher = new Stub() {
@Override
public void onRotationChanged(final int rotation) throws RemoteException {
@@ -105,7 +106,7 @@
if (shouldOverrideUserLockPrefs(rotation)) {
setRotationLockedAtAngle(rotation);
}
- setRotateSuggestionButtonState(false /* visible */, true /* forced */);
+ setRotateSuggestionButtonState(false /* visible */, true /* hideImmediately */);
}
if (mRotWatcherListener != null) {
@@ -192,10 +193,14 @@
}
void setRotateSuggestionButtonState(boolean visible) {
- setRotateSuggestionButtonState(visible, false /* force */);
+ setRotateSuggestionButtonState(visible, false /* hideImmediately */);
}
- void setRotateSuggestionButtonState(final boolean visible, final boolean force) {
+ /**
+ * Change the visibility of rotate suggestion button. If {@code hideImmediately} is true,
+ * it doesn't wait until the completion of the running animation.
+ */
+ void setRotateSuggestionButtonState(final boolean visible, final boolean hideImmediately) {
// At any point the the button can become invisible because an a11y service became active.
// Similarly, a call to make the button visible may be rejected because an a11y service is
// active. Must account for this.
@@ -236,7 +241,7 @@
} else { // Hide
mViewRippler.stop(); // Prevent any pending ripples, force hide or not
- if (force) {
+ if (hideImmediately) {
// If a hide animator is running stop it and make invisible
if (mRotateHideAnimator != null && mRotateHideAnimator.isRunning()) {
mRotateHideAnimator.pause();
@@ -263,12 +268,29 @@
}
}
+ void setRecentsAnimationRunning(boolean running) {
+ mIsRecentsAnimationRunning = running;
+ updateRotationButtonStateInOverview();
+ }
+
+ void setHomeRotationEnabled(boolean enabled) {
+ mHomeRotationEnabled = enabled;
+ updateRotationButtonStateInOverview();
+ }
+
+ private void updateRotationButtonStateInOverview() {
+ if (mIsRecentsAnimationRunning && !mHomeRotationEnabled) {
+ setRotateSuggestionButtonState(false, true /* hideImmediately */ );
+ }
+ }
+
void setDarkIntensity(float darkIntensity) {
mRotationButton.setDarkIntensity(darkIntensity);
}
void onRotationProposal(int rotation, int windowRotation, boolean isValid) {
- if (!mRotationButton.acceptRotationProposal()) {
+ if (!mRotationButton.acceptRotationProposal() || (!mHomeRotationEnabled
+ && mIsRecentsAnimationRunning)) {
return;
}
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 fc615de..be513f3 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -187,6 +187,7 @@
private final Executor mMainExecutor;
private final Rect mPipExcludedBounds = new Rect();
+ private final Rect mNavBarOverlayExcludedBounds = new Rect();
private final Region mExcludeRegion = new Region();
private final Region mUnrestrictedExcludeRegion = new Region();
@@ -366,6 +367,10 @@
mTouchSlop = mViewConfiguration.getScaledTouchSlop() * backGestureSlop;
}
+ public void updateNavigationBarOverlayExcludeRegion(Rect exclude) {
+ mNavBarOverlayExcludedBounds.set(exclude);
+ }
+
private void onNavigationSettingsChanged() {
boolean wasBackAllowed = isHandlingGestures();
updateCurrentUserResources();
@@ -629,8 +634,9 @@
return false;
}
- // If the point is inside the PiP excluded bounds, then drop it.
- if (mPipExcludedBounds.contains(x, y)) {
+ // 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)) {
return false;
}
@@ -893,6 +899,7 @@
pw.println(" mExcludeRegion=" + mExcludeRegion);
pw.println(" mUnrestrictedExcludeRegion=" + mUnrestrictedExcludeRegion);
pw.println(" mPipExcludedBounds=" + mPipExcludedBounds);
+ pw.println(" mNavBarOverlayExcludedBounds=" + mNavBarOverlayExcludedBounds);
pw.println(" mEdgeWidthLeft=" + mEdgeWidthLeft);
pw.println(" mEdgeWidthRight=" + mEdgeWidthRight);
pw.println(" mLeftInset=" + mLeftInset);
diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleStoryIconFactory.java b/packages/SystemUI/src/com/android/systemui/people/PeopleStoryIconFactory.java
index 81df107..f3cb359 100644
--- a/packages/SystemUI/src/com/android/systemui/people/PeopleStoryIconFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/people/PeopleStoryIconFactory.java
@@ -28,7 +28,6 @@
import android.graphics.drawable.Drawable;
import android.util.IconDrawableFactory;
import android.util.Log;
-import android.util.TypedValue;
import com.android.settingslib.Utils;
import com.android.systemui.R;
@@ -37,7 +36,7 @@
private static final int PADDING = 2;
private static final int RING_WIDTH = 2;
- private static final int MAX_BADGE_SIZE = 36;
+ private static final int MAX_BADGE_SIZE = 40;
final PackageManager mPackageManager;
final IconDrawableFactory mIconDrawableFactory;
@@ -51,15 +50,15 @@
PeopleStoryIconFactory(Context context, PackageManager pm,
IconDrawableFactory iconDrawableFactory, int iconSizeDp) {
+ context.setTheme(android.R.style.Theme_DeviceDefault_DayNight);
mIconBitmapSize = (int) (iconSizeDp * context.getResources().getDisplayMetrics().density);
mDensity = context.getResources().getDisplayMetrics().density;
mIconSize = mDensity * iconSizeDp;
mPackageManager = pm;
mIconDrawableFactory = iconDrawableFactory;
mImportantConversationColor = context.getColor(R.color.important_conversation);
- TypedValue typedValue = new TypedValue();
- context.getTheme().resolveAttribute(android.R.attr.colorAccent, typedValue, true);
- mAccentColor = context.getColor(typedValue.resourceId);
+ mAccentColor = Utils.getColorAttr(context,
+ com.android.internal.R.attr.colorAccentPrimary).getDefaultColor();
mContext = context;
}
diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java b/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java
index 9fc9cad..59c7fd1 100644
--- a/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java
@@ -55,6 +55,7 @@
import android.util.IconDrawableFactory;
import android.util.Log;
import android.util.Pair;
+import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.widget.RemoteViews;
@@ -87,7 +88,6 @@
private static final int DAYS_IN_A_WEEK = 7;
private static final int ONE_DAY = 1;
- private static final int MAX_WEEKS = 2;
public static final int LAYOUT_SMALL = 0;
public static final int LAYOUT_MEDIUM = 1;
@@ -95,10 +95,11 @@
private static final int MIN_CONTENT_MAX_LINES = 2;
- private static final int FIXED_HEIGHT_DIMENS_FOR_LARGE_CONTENT = 14 + 12 + 4 + 16;
+ private static final int FIXED_HEIGHT_DIMENS_FOR_LARGE_NOTIF_CONTENT = 16 + 22 + 8 + 16;
+ private static final int FIXED_HEIGHT_DIMENS_FOR_LARGE_STATUS_CONTENT = 16 + 16 + 24 + 4 + 16;
private static final int MIN_MEDIUM_VERTICAL_PADDING = 4;
private static final int MAX_MEDIUM_PADDING = 16;
- private static final int FIXED_HEIGHT_DIMENS_FOR_MEDIUM_CONTENT_BEFORE_PADDING = 4 + 4;
+ private static final int FIXED_HEIGHT_DIMENS_FOR_MEDIUM_CONTENT_BEFORE_PADDING = 8 + 4;
private static final int FIXED_HEIGHT_DIMENS_FOR_SMALL = 6 + 4 + 8;
private static final int FIXED_WIDTH_DIMENS_FOR_SMALL = 4 + 4;
@@ -276,12 +277,15 @@
}
private void setMaxLines(RemoteViews views, boolean showSender) {
- int textSize = mLayoutSize == LAYOUT_LARGE ? getSizeInDp(
- R.dimen.content_text_size_for_large)
- : getSizeInDp(R.dimen.content_text_size_for_medium);
- int lineHeight = getLineHeight(textSize);
- int notificationContentHeight = getContentHeightForLayout(lineHeight);
- int maxAdaptiveLines = Math.floorDiv(notificationContentHeight, lineHeight);
+ int nameHeight = getLineHeightFromResource(R.dimen.name_text_size_for_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);
// Save a line for sender's name, if present.
@@ -289,10 +293,12 @@
views.setInt(R.id.text_content, "setMaxLines", maxLines);
}
- private int getLineHeight(int textSize) {
+ private int getLineHeightFromResource(int resId) {
try {
TextView text = new TextView(mContext);
- text.setTextSize(textSize);
+ text.setTextSize(TypedValue.COMPLEX_UNIT_PX,
+ mContext.getResources().getDimension(resId));
+ text.setTextAppearance(android.R.style.TextAppearance_DeviceDefault);
int lineHeight = (int) (text.getLineHeight() / mDensity);
return lineHeight;
} catch (Exception e) {
@@ -310,15 +316,17 @@
return (int) (context.getResources().getDimension(dimenResourceId) / density);
}
- private int getContentHeightForLayout(int lineHeight) {
+ private int getContentHeightForLayout(int lineHeight, boolean hasPredefinedIcon) {
switch (mLayoutSize) {
case LAYOUT_MEDIUM:
return mHeight - (lineHeight + FIXED_HEIGHT_DIMENS_FOR_MEDIUM_CONTENT_BEFORE_PADDING
+ mMediumVerticalPadding * 2);
case LAYOUT_LARGE:
+ int fixedHeight = hasPredefinedIcon ? FIXED_HEIGHT_DIMENS_FOR_LARGE_STATUS_CONTENT
+ : FIXED_HEIGHT_DIMENS_FOR_LARGE_NOTIF_CONTENT;
return mHeight - (getSizeInDp(
R.dimen.max_people_avatar_size_for_large_content) + lineHeight
- + FIXED_HEIGHT_DIMENS_FOR_LARGE_CONTENT);
+ + fixedHeight);
default:
return -1;
}
@@ -326,7 +334,7 @@
/** Calculates the best layout relative to the size in {@code options}. */
private int getLayoutSize() {
- if (mHeight >= getSizeInDp(R.dimen.required_width_for_large)
+ if (mHeight >= getSizeInDp(R.dimen.required_height_for_large)
&& mWidth >= getSizeInDp(R.dimen.required_width_for_large)) {
if (DEBUG) Log.d(TAG, "Large view for mWidth: " + mWidth + " mHeight: " + mHeight);
return LAYOUT_LARGE;
@@ -334,8 +342,9 @@
// Small layout used below a certain minimum mWidth with any mHeight.
if (mWidth >= getSizeInDp(R.dimen.required_width_for_medium)) {
int spaceAvailableForPadding =
- mHeight - (getSizeInDp(R.dimen.avatar_size_for_medium) + 4 + getLineHeight(
- getSizeInDp(R.dimen.name_text_size_for_medium)));
+ mHeight - (getSizeInDp(R.dimen.avatar_size_for_medium)
+ + getLineHeightFromResource(
+ R.dimen.name_text_size_for_content));
if (DEBUG) {
Log.d(TAG, "Medium view for mWidth: " + mWidth + " mHeight: " + mHeight
+ " with padding space: " + spaceAvailableForPadding);
@@ -365,26 +374,32 @@
// Calculate adaptive avatar size for remaining layouts.
if (layoutId == R.layout.people_tile_small) {
int avatarHeightSpace = mHeight - (FIXED_HEIGHT_DIMENS_FOR_SMALL + Math.max(18,
- getLineHeight(getSizeInDp(
- R.dimen.name_text_size_for_small))));
+ getLineHeightFromResource(
+ R.dimen.name_text_size_for_small)));
int avatarWidthSpace = mWidth - FIXED_WIDTH_DIMENS_FOR_SMALL;
avatarSize = Math.min(avatarHeightSpace, avatarWidthSpace);
}
- if (layoutId == R.layout.people_tile_large_with_content) {
- avatarSize = mHeight - (FIXED_HEIGHT_DIMENS_FOR_LARGE_CONTENT + (getLineHeight(
- getSizeInDp(R.dimen.content_text_size_for_large))
- * 3));
+ if (layoutId == R.layout.people_tile_large_with_notification_content) {
+ avatarSize = mHeight - (FIXED_HEIGHT_DIMENS_FOR_LARGE_NOTIF_CONTENT + (
+ getLineHeightFromResource(
+ R.dimen.content_text_size_for_large)
+ * 3));
+ return Math.min(avatarSize, getSizeInDp(
+ R.dimen.max_people_avatar_size_for_large_content));
+ } else if (layoutId == R.layout.people_tile_large_with_status_content) {
+ avatarSize = mHeight - (FIXED_HEIGHT_DIMENS_FOR_LARGE_STATUS_CONTENT + (
+ getLineHeightFromResource(R.dimen.content_text_size_for_large)
+ * 3));
return Math.min(avatarSize, getSizeInDp(
R.dimen.max_people_avatar_size_for_large_content));
}
if (layoutId == R.layout.people_tile_large_empty) {
- int avatarHeightSpace = mHeight - (14 + 14 + getLineHeight(
- getSizeInDp(R.dimen.name_text_size_for_large))
- + getLineHeight(
- getSizeInDp(R.dimen.content_text_size_for_large))
- + 16 + 10 + 14);
+ int avatarHeightSpace = mHeight - (14 + 14 + getLineHeightFromResource(
+ R.dimen.name_text_size_for_large)
+ + getLineHeightFromResource(R.dimen.content_text_size_for_large)
+ + 16 + 10 + 16);
int avatarWidthSpace = mWidth - (14 + 14);
avatarSize = Math.min(avatarHeightSpace, avatarWidthSpace);
}
@@ -449,17 +464,28 @@
}
private RemoteViews createMissedCallRemoteViews() {
- RemoteViews views = getViewForContentLayout();
+ RemoteViews views = setViewForContentLayout(new RemoteViews(mContext.getPackageName(),
+ getLayoutForContent()));
views.setViewVisibility(R.id.predefined_icon, View.VISIBLE);
+ views.setViewVisibility(R.id.text_content, View.VISIBLE);
views.setViewVisibility(R.id.messages_count, View.GONE);
setMaxLines(views, false);
views.setTextViewText(R.id.text_content, mTile.getNotificationContent());
+ views.setColorAttr(R.id.text_content, "setTextColor", android.R.attr.colorError);
+ views.setColorAttr(R.id.predefined_icon, "setColorFilter", android.R.attr.colorError);
views.setImageViewResource(R.id.predefined_icon, R.drawable.ic_phone_missed);
+ if (mLayoutSize == LAYOUT_LARGE) {
+ views.setInt(R.id.content, "setGravity", Gravity.BOTTOM);
+ views.setViewLayoutHeightDimen(R.id.predefined_icon, R.dimen.large_predefined_icon);
+ views.setViewLayoutWidthDimen(R.id.predefined_icon, R.dimen.large_predefined_icon);
+ }
+ setAvailabilityDotPadding(views, R.dimen.availability_dot_notification_padding);
return views;
}
private RemoteViews createNotificationRemoteViews() {
- RemoteViews views = getViewForContentLayout();
+ RemoteViews views = setViewForContentLayout(new RemoteViews(mContext.getPackageName(),
+ getLayoutForNotificationContent()));
CharSequence sender = mTile.getNotificationSender();
Uri image = mTile.getNotificationDataUri();
if (image != null) {
@@ -474,6 +500,11 @@
views = decorateBackground(views, content);
views.setColorAttr(R.id.text_content, "setTextColor", android.R.attr.textColorPrimary);
views.setTextViewText(R.id.text_content, mTile.getNotificationContent());
+ if (mLayoutSize == LAYOUT_LARGE) {
+ views.setViewPadding(R.id.name, 0, 0, 0,
+ mContext.getResources().getDimensionPixelSize(
+ R.dimen.above_notification_text_padding));
+ }
views.setViewVisibility(R.id.image, View.GONE);
views.setImageViewResource(R.id.predefined_icon, R.drawable.ic_message);
}
@@ -491,6 +522,7 @@
} else {
views.setViewVisibility(R.id.subtext, View.GONE);
}
+ setAvailabilityDotPadding(views, R.dimen.availability_dot_notification_padding);
return views;
}
@@ -513,7 +545,8 @@
}
private RemoteViews createStatusRemoteViews(ConversationStatus status) {
- RemoteViews views = getViewForContentLayout();
+ RemoteViews views = setViewForContentLayout(new RemoteViews(mContext.getPackageName(),
+ getLayoutForContent()));
CharSequence statusText = status.getDescription();
if (TextUtils.isEmpty(statusText)) {
statusText = getStatusTextByType(status.getActivity());
@@ -545,11 +578,27 @@
android.R.attr.textColorSecondary);
setMaxLines(views, false);
}
+ setAvailabilityDotPadding(views, R.dimen.availability_dot_status_padding);
// TODO: Set status pre-defined icons
views.setImageViewResource(R.id.predefined_icon, R.drawable.ic_person);
return views;
}
+ /**
+ * Update the padding of the availability dot. The padding on the availability dot decreases
+ * on the status layouts compared to all other layouts.
+ */
+ private void setAvailabilityDotPadding(RemoteViews views, int resId) {
+ boolean isLeftToRight = TextUtils.getLayoutDirectionFromLocale(Locale.getDefault())
+ == View.LAYOUT_DIRECTION_LTR;
+ int startPadding = mContext.getResources().getDimensionPixelSize(resId);
+ int bottomPadding = mContext.getResources().getDimensionPixelSize(
+ R.dimen.medium_content_padding_above_name);
+ views.setViewPadding(R.id.medium_content,
+ isLeftToRight ? startPadding : 0, 0, isLeftToRight ? 0 : startPadding,
+ bottomPadding);
+ }
+
@Nullable
private ConversationStatus getBirthdayStatus(
List<ConversationStatus> statuses) {
@@ -718,9 +767,7 @@
return null;
}
- private RemoteViews getViewForContentLayout() {
- RemoteViews views = new RemoteViews(mContext.getPackageName(),
- getLayoutForContent());
+ private RemoteViews setViewForContentLayout(RemoteViews views) {
if (mLayoutSize == LAYOUT_SMALL) {
views.setViewVisibility(R.id.predefined_icon, View.VISIBLE);
views.setViewVisibility(R.id.name, View.GONE);
@@ -734,13 +781,34 @@
}
if (mLayoutSize == LAYOUT_MEDIUM) {
+ // Maximize vertical padding with an avatar size of 48dp and name on medium.
if (DEBUG) Log.d(TAG, "Set vertical padding: " + mMediumVerticalPadding);
int horizontalPadding = (int) Math.floor(MAX_MEDIUM_PADDING * mDensity);
int verticalPadding = (int) Math.floor(mMediumVerticalPadding * mDensity);
views.setViewPadding(R.id.content, horizontalPadding, verticalPadding,
horizontalPadding,
verticalPadding);
+ // Expand the name font on medium if there's space.
+ int heightRequiredForMaxContentText = (int) (mContext.getResources().getDimension(
+ R.dimen.medium_height_for_max_name_text_size) / mDensity);
+ if (mHeight > heightRequiredForMaxContentText) {
+ views.setTextViewTextSize(R.id.name, TypedValue.COMPLEX_UNIT_PX,
+ (int) mContext.getResources().getDimension(
+ R.dimen.max_name_text_size_for_medium));
+ }
}
+
+ if (mLayoutSize == LAYOUT_LARGE) {
+ // Decrease the view padding below the name on all layouts besides notification "text".
+ views.setViewPadding(R.id.name, 0, 0, 0,
+ mContext.getResources().getDimensionPixelSize(
+ R.dimen.below_name_text_padding));
+ }
+
+ // For all layouts except Missed Calls, ensure predefined icon is regular sized.
+ views.setViewLayoutHeightDimen(R.id.predefined_icon, R.dimen.regular_predefined_icon);
+ views.setViewLayoutWidthDimen(R.id.predefined_icon, R.dimen.regular_predefined_icon);
+
views.setViewVisibility(R.id.messages_count, View.GONE);
if (mTile.getUserName() != null) {
views.setTextViewText(R.id.name, mTile.getUserName());
@@ -784,12 +852,24 @@
}
}
+ private int getLayoutForNotificationContent() {
+ switch (mLayoutSize) {
+ case LAYOUT_MEDIUM:
+ return R.layout.people_tile_medium_with_content;
+ case LAYOUT_LARGE:
+ return R.layout.people_tile_large_with_notification_content;
+ case LAYOUT_SMALL:
+ default:
+ return R.layout.people_tile_small;
+ }
+ }
+
private int getLayoutForContent() {
switch (mLayoutSize) {
case LAYOUT_MEDIUM:
return R.layout.people_tile_medium_with_content;
case LAYOUT_LARGE:
- return R.layout.people_tile_large_with_content;
+ return R.layout.people_tile_large_with_status_content;
case LAYOUT_SMALL:
default:
return R.layout.people_tile_small;
@@ -832,19 +912,18 @@
if (durationSinceLastInteraction.toDays() <= ONE_DAY) {
return null;
} else if (durationSinceLastInteraction.toDays() < DAYS_IN_A_WEEK) {
- return context.getString(R.string.timestamp, formatter.formatMeasures(
+ return context.getString(R.string.days_timestamp, formatter.formatMeasures(
new Measure(durationSinceLastInteraction.toDays(),
MeasureUnit.DAY)));
- } else if (durationSinceLastInteraction.toDays() <= DAYS_IN_A_WEEK * 2) {
- return context.getString(durationSinceLastInteraction.toDays() == DAYS_IN_A_WEEK
- ? R.string.timestamp : R.string.over_timestamp,
- formatter.formatMeasures(
- new Measure(durationSinceLastInteraction.toDays() / DAYS_IN_A_WEEK,
- MeasureUnit.WEEK)));
+ } else if (durationSinceLastInteraction.toDays() == DAYS_IN_A_WEEK) {
+ return context.getString(R.string.one_week_timestamp);
+ } else if (durationSinceLastInteraction.toDays() < DAYS_IN_A_WEEK * 2) {
+ return context.getString(R.string.over_one_week_timestamp);
+ } else if (durationSinceLastInteraction.toDays() == DAYS_IN_A_WEEK * 2) {
+ return context.getString(R.string.two_weeks_timestamp);
} else {
// Over 2 weeks ago
- return context.getString(R.string.over_timestamp,
- formatter.formatMeasures(new Measure(MAX_WEEKS, MeasureUnit.WEEK)));
+ return context.getString(R.string.over_two_weeks_timestamp);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
index 0335319..2d0d87d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
@@ -37,6 +37,7 @@
import android.widget.Switch;
import android.widget.TextView;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.UiEventLogger;
import com.android.systemui.Dependency;
@@ -57,7 +58,8 @@
private ViewGroup mDetailContent;
protected TextView mDetailSettingsButton;
protected TextView mDetailDoneButton;
- private QSDetailClipper mClipper;
+ @VisibleForTesting
+ QSDetailClipper mClipper;
private DetailAdapter mDetailAdapter;
private QSPanelController mQsPanelController;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index 53b4d5f..34c654c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -112,6 +112,17 @@
* otherwise.
*/
private boolean mTranslateWhileExpanding;
+ private boolean mPulseExpanding;
+
+ /**
+ * Are we currently transitioning from lockscreen to the full shade?
+ */
+ private boolean mTransitioningToFullShade;
+
+ /**
+ * Whether the next Quick settings
+ */
+ private boolean mAnimateNextQsUpdate;
@Inject
public QSFragment(RemoteInputQuickSettingsDisabler remoteInputQsDisabler,
@@ -265,6 +276,11 @@
}
}
+ @Override
+ public boolean isFullyCollapsed() {
+ return mLastQSExpansion == 0.0f || mLastQSExpansion == -1;
+ }
+
private void setEditLocation(View view) {
View edit = view.findViewById(android.R.id.edit);
int[] loc = edit.getLocationOnScreen();
@@ -335,14 +351,22 @@
}
@Override
- public void setShowCollapsedOnKeyguard(boolean showCollapsedOnKeyguard) {
- if (showCollapsedOnKeyguard != mShowCollapsedOnKeyguard) {
- mShowCollapsedOnKeyguard = showCollapsedOnKeyguard;
+ public void setPulseExpanding(boolean pulseExpanding) {
+ if (pulseExpanding != mPulseExpanding) {
+ mPulseExpanding = pulseExpanding;
+ updateShowCollapsedOnKeyguard();
+ }
+ }
+
+ private void updateShowCollapsedOnKeyguard() {
+ boolean showCollapsed = mPulseExpanding || mTransitioningToFullShade;
+ if (showCollapsed != mShowCollapsedOnKeyguard) {
+ mShowCollapsedOnKeyguard = showCollapsed;
updateQsState();
if (mQSAnimator != null) {
- mQSAnimator.setShowCollapsedOnKeyguard(showCollapsedOnKeyguard);
+ mQSAnimator.setShowCollapsedOnKeyguard(showCollapsed);
}
- if (!showCollapsedOnKeyguard && isKeyguardShowing()) {
+ if (!showCollapsed && isKeyguardShowing()) {
setQsExpansion(mLastQSExpansion, 0);
}
}
@@ -411,13 +435,24 @@
}
@Override
- public void setQsExpansion(float expansion, float headerTranslation) {
- if (DEBUG) Log.d(TAG, "setQSExpansion " + expansion + " " + headerTranslation);
+ public void setTransitionToFullShadeAmount(float pxAmount, boolean animated) {
+ boolean isTransitioningToFullShade = pxAmount > 0;
+ if (isTransitioningToFullShade != mTransitioningToFullShade) {
+ mTransitioningToFullShade = isTransitioningToFullShade;
+ updateShowCollapsedOnKeyguard();
+ setQsExpansion(mLastQSExpansion, mLastHeaderTranslation);
+ }
+ }
+ @Override
+ public void setQsExpansion(float expansion, float proposedTranslation) {
+ if (DEBUG) Log.d(TAG, "setQSExpansion " + expansion + " " + proposedTranslation);
+ float headerTranslation = mTransitioningToFullShade ? 0 : proposedTranslation;
if (mQSAnimator != null) {
final boolean showQSOnLockscreen = expansion > 0;
final boolean showQSUnlocked = headerTranslation == 0 || !mTranslateWhileExpanding;
- mQSAnimator.startAlphaAnimation(showQSOnLockscreen || showQSUnlocked);
+ mQSAnimator.startAlphaAnimation(showQSOnLockscreen || showQSUnlocked
+ || mTransitioningToFullShade);
}
mContainer.setExpansion(expansion);
final float translationScaleY = (mTranslateWhileExpanding
@@ -542,18 +577,6 @@
}
@Override
- public void animateHeaderSlidingIn(long delay) {
- if (DEBUG) Log.d(TAG, "animateHeaderSlidingIn");
- // If the QS is already expanded we don't need to slide in the header as it's already
- // visible.
- if (!mQsExpanded && getView().getTranslationY() != 0) {
- mHeaderAnimating = true;
- mDelay = delay;
- getView().getViewTreeObserver().addOnPreDrawListener(mStartHeaderSlidingIn);
- }
- }
-
- @Override
public void animateHeaderSlidingOut() {
if (DEBUG) Log.d(TAG, "animateHeaderSlidingOut");
if (getView().getY() == -mHeader.getHeight()) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java
index 8280f98..2e771d6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java
@@ -244,11 +244,13 @@
public static int getIconColorForState(Context context, int state) {
switch (state) {
case Tile.STATE_UNAVAILABLE:
- return Utils.getColorAttrDefaultColor(context, android.R.attr.textColorTertiary);
+ return Utils.applyAlpha(QSTileViewImpl.UNAVAILABLE_ALPHA,
+ Utils.getColorAttrDefaultColor(context, android.R.attr.textColorPrimary));
case Tile.STATE_INACTIVE:
return Utils.getColorAttrDefaultColor(context, android.R.attr.textColorPrimary);
case Tile.STATE_ACTIVE:
- return Utils.getColorAttrDefaultColor(context, android.R.attr.colorPrimary);
+ return Utils.getColorAttrDefaultColor(context,
+ android.R.attr.textColorPrimaryInverse);
default:
Log.e("QSIconView", "Invalid state " + state);
return 0;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
index b3ec39f..cd76b4d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
@@ -61,6 +61,7 @@
private const val LABEL_NAME = "label"
private const val SECONDARY_LABEL_NAME = "secondaryLabel"
private const val CHEVRON_NAME = "chevron"
+ const val UNAVAILABLE_ALPHA = 0.3f
}
override var heightOverride: Int = HeightOverrideable.NO_OVERRIDE
@@ -68,15 +69,20 @@
private val colorActive = Utils.getColorAttrDefaultColor(context,
com.android.internal.R.attr.colorAccentPrimary)
private val colorInactive = Utils.getColorAttrDefaultColor(context, R.attr.offStateColor)
- private val colorUnavailable =
- Utils.getColorAttrDefaultColor(context, android.R.attr.colorBackground)
+ private val colorUnavailable = Utils.applyAlpha(UNAVAILABLE_ALPHA, colorInactive)
private val colorLabelActive =
Utils.getColorAttrDefaultColor(context, android.R.attr.textColorPrimaryInverse)
private val colorLabelInactive =
Utils.getColorAttrDefaultColor(context, android.R.attr.textColorPrimary)
- private val colorLabelUnavailable =
- Utils.getColorAttrDefaultColor(context, android.R.attr.textColorTertiary)
+ private val colorLabelUnavailable = Utils.applyAlpha(UNAVAILABLE_ALPHA, colorLabelInactive)
+
+ private val colorSecondaryLabelActive =
+ Utils.getColorAttrDefaultColor(context, android.R.attr.textColorSecondaryInverse)
+ private val colorSecondaryLabelInactive =
+ Utils.getColorAttrDefaultColor(context, android.R.attr.textColorSecondary)
+ private val colorSecondaryLabelUnavailable =
+ Utils.applyAlpha(UNAVAILABLE_ALPHA, colorSecondaryLabelInactive)
private lateinit var label: TextView
protected lateinit var secondaryLabel: TextView
@@ -404,7 +410,7 @@
),
colorValuesHolder(
SECONDARY_LABEL_NAME,
- label.currentTextColor,
+ secondaryLabel.currentTextColor,
getSecondaryLabelColorForState(state.state)
),
colorValuesHolder(
@@ -418,7 +424,7 @@
setAllColors(
getBackgroundColorForState(state.state),
getLabelColorForState(state.state),
- getLabelColorForState(state.state),
+ getSecondaryLabelColorForState(state.state),
getChevronColorForState(state.state)
)
}
@@ -533,8 +539,9 @@
private fun getSecondaryLabelColorForState(state: Int): Int {
return when (state) {
- Tile.STATE_ACTIVE -> colorLabelActive
- Tile.STATE_INACTIVE, Tile.STATE_UNAVAILABLE -> colorLabelUnavailable
+ Tile.STATE_ACTIVE -> colorSecondaryLabelActive
+ Tile.STATE_INACTIVE -> colorSecondaryLabelInactive
+ Tile.STATE_UNAVAILABLE -> colorSecondaryLabelUnavailable
else -> {
Log.e(TAG, "Invalid state $state")
0
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 71f42d8..11b0e01 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt
@@ -40,6 +40,7 @@
import com.android.systemui.qs.QSHost
import com.android.systemui.qs.logging.QSLogger
import com.android.systemui.qs.tileimpl.QSTileImpl
+import com.android.systemui.statusbar.policy.KeyguardStateController
import java.util.concurrent.atomic.AtomicBoolean
import javax.inject.Inject
@@ -52,7 +53,8 @@
statusBarStateController: StatusBarStateController,
activityStarter: ActivityStarter,
qsLogger: QSLogger,
- private val controlsComponent: ControlsComponent
+ private val controlsComponent: ControlsComponent,
+ private val keyguardStateController: KeyguardStateController
) : QSTileImpl<QSTile.State>(
host,
backgroundLooper,
@@ -101,11 +103,15 @@
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK)
putExtra(ControlsUiController.EXTRA_ANIMATE, true)
}
-
- val animationController = view?.let {
- ActivityLaunchAnimator.Controller.fromView(it)
+ if (keyguardStateController.isUnlocked()) {
+ val animationController = view?.let {
+ ActivityLaunchAnimator.Controller.fromView(it)
+ }
+ mActivityStarter.startActivity(i, true /* dismissShade */, animationController)
+ } else {
+ mHost.collapsePanels()
+ mContext.startActivity(i)
}
- mActivityStarter.startActivity(i, true /* dismissShade */, animationController)
}
}
}
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 85b835a..e467925 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java
@@ -152,7 +152,8 @@
@Override
protected void handleUpdateState(State state, Object arg) {
- state.label = mLabel;
+ CharSequence label = mQuickAccessWalletClient.getServiceLabel();
+ state.label = label == null ? mLabel : label;
state.contentDescription = state.label;
state.icon = ResourceIcon.get(R.drawable.ic_wallet_lockscreen);
boolean isDeviceLocked = !mKeyguardStateController.isUnlocked();
@@ -197,7 +198,8 @@
@Override
public CharSequence getTileLabel() {
- return mLabel;
+ CharSequence label = mQuickAccessWalletClient.getServiceLabel();
+ return label == null ? mLabel : label;
}
private void queryWalletCards() {
@@ -227,7 +229,9 @@
}
int selectedIndex = response.getSelectedIndex();
if (selectedIndex >= cards.size()) {
- Log.d(TAG, "Selected card index out of bounds.");
+ Log.w(TAG, "Error retrieving cards: Invalid selected card index.");
+ mSelectedCard = null;
+ mCardViewDrawable = null;
return;
}
mSelectedCard = cards.get(selectedIndex);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
index 7bde64b..8df8c63 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
@@ -125,25 +125,14 @@
} else {
state.slash.isSlashed = true;
}
- state.label = mContext.getString(R.string.quick_settings_work_mode_label);
+ state.label = getTileLabel();
state.contentDescription = state.label;
state.expandedAccessibilityClassName = Switch.class.getName();
state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
- state.secondaryLabel = state.value ? "" :
- mContext.getString(R.string.quick_settings_work_mode_paused);
}
@Override
public int getMetricsCategory() {
return MetricsEvent.QS_WORKMODE;
}
-
- @Override
- protected String composeChangeAnnouncement() {
- if (mState.value) {
- return mContext.getString(R.string.accessibility_quick_settings_work_mode_changed_on);
- } else {
- return mContext.getString(R.string.accessibility_quick_settings_work_mode_changed_off);
- }
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index 63adbd0..20c3e81 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -259,6 +259,21 @@
}
}
+ @Override
+ public void setHomeRotationEnabled(boolean enabled) {
+ if (!verifyCaller("setHomeRotationEnabled")) {
+ return;
+ }
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mHandler.post(() -> {
+ mHandler.post(() -> notifyHomeRotationEnabled(enabled));
+ });
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
private boolean sendEvent(int action, int code) {
long when = SystemClock.uptimeMillis();
final KeyEvent ev = new KeyEvent(when, when, action, code, 0 /* repeat */,
@@ -847,6 +862,12 @@
}
}
+ private void notifyHomeRotationEnabled(boolean enabled) {
+ for (int i = mConnectionCallbacks.size() - 1; i >= 0; --i) {
+ mConnectionCallbacks.get(i).onHomeRotationEnabled(enabled);
+ }
+ }
+
private void notifyConnectionChanged() {
for (int i = mConnectionCallbacks.size() - 1; i >= 0; --i) {
mConnectionCallbacks.get(i).onConnectionChanged(mOverviewProxy != null);
@@ -994,6 +1015,7 @@
default void onToggleRecentApps() {}
/** Notify changes in the nav bar button alpha */
default void onNavBarButtonAlphaChanged(float alpha, boolean animate) {}
+ default void onHomeRotationEnabled(boolean enabled) {}
default void onSystemUiStateChanged(int sysuiStateFlags) {}
default void onAssistantProgress(@FloatRange(from = 0.0, to = 1.0) float progress) {}
default void onAssistantGestureCompletion(float velocity) {}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
index 7c2d476..1f9221c 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
@@ -401,9 +401,6 @@
if (DEBUG_UI) {
Log.d(TAG, "reloadAssets()");
}
- if (mScreenshotView != null && mScreenshotView.isAttachedToWindow()) {
- mWindow.clearContentView(); // Is there a simpler way to say "remove screenshotView?"
- }
// respect the display cutout in landscape (since we'd otherwise overlap) but not portrait
int orientation = mContext.getResources().getConfiguration().orientation;
@@ -497,6 +494,17 @@
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()) {
@@ -507,12 +515,6 @@
mAccessibilityManager.sendAccessibilityEvent(event);
}
- if (mConfigChanges.applyNewConfig(mContext.getResources())) {
- if (DEBUG_UI) {
- Log.d(TAG, "saveScreenshot: reloading assets");
- }
- reloadAssets();
- }
if (mScreenshotView.isAttachedToWindow()) {
// if we didn't already dismiss for another reason
@@ -526,6 +528,9 @@
mScreenshotView.reset();
}
+ int orientation = mContext.getResources().getConfiguration().orientation;
+ mScreenshotView.updateOrientation(orientation == ORIENTATION_PORTRAIT);
+
mScreenBitmap = screenshot;
if (!isUserSetupComplete()) {
@@ -556,6 +561,12 @@
mLastScrollCaptureRequest = mScrollCaptureClient.request(DEFAULT_DISPLAY);
mLastScrollCaptureRequest.addListener(() ->
onScrollCaptureResponseReady(mLastScrollCaptureRequest), mMainExecutor);
+ mWindow.peekDecorView().getViewRootImpl().setActivityConfigCallback(
+ (overrideConfig, newDisplayId) -> {
+ if (mConfigChanges.applyNewConfig(mContext.getResources())) {
+ updateDisplayCutout();
+ }
+ });
});
attachWindow();
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
index 70b1133..71a152d 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
@@ -60,6 +60,7 @@
import android.view.MotionEvent;
import android.view.TouchDelegate;
import android.view.View;
+import android.view.ViewGroup;
import android.view.ViewOutlineProvider;
import android.view.ViewTreeObserver;
import android.view.WindowInsets;
@@ -350,6 +351,23 @@
mScreenshotPreview.setImageDrawable(createScreenDrawable(mResources, bitmap, screenInsets));
}
+ void updateOrientation(boolean portrait) {
+ mOrientationPortrait = portrait;
+ int screenshotFixedSize =
+ mContext.getResources().getDimensionPixelSize(R.dimen.global_screenshot_x_scale);
+ ViewGroup.LayoutParams params = mScreenshotPreview.getLayoutParams();
+ if (portrait) {
+ params.width = screenshotFixedSize;
+ params.height = LayoutParams.WRAP_CONTENT;
+ mScreenshotPreview.setScaleType(ImageView.ScaleType.FIT_START);
+ } else {
+ params.width = LayoutParams.WRAP_CONTENT;
+ params.height = screenshotFixedSize;
+ mScreenshotPreview.setScaleType(ImageView.ScaleType.FIT_END);
+ }
+ mScreenshotPreview.setLayoutParams(params);
+ }
+
AnimatorSet createScreenshotDropInAnimation(Rect bounds, boolean showFlash) {
if (DEBUG_ANIM) {
Log.d(TAG, "createAnim: bounds=" + bounds + " showFlash=" + showFlash);
diff --git a/packages/SystemUI/src/com/android/systemui/scrim/ScrimView.java b/packages/SystemUI/src/com/android/systemui/scrim/ScrimView.java
index 1a5c9ee..7530681 100644
--- a/packages/SystemUI/src/com/android/systemui/scrim/ScrimView.java
+++ b/packages/SystemUI/src/com/android/systemui/scrim/ScrimView.java
@@ -294,7 +294,6 @@
/**
* Make bottom edge concave so overlap between layers is not visible for alphas between 0 and 1
- * @return height of concavity
*/
public void enableBottomEdgeConcave(boolean clipScrim) {
if (mDrawable instanceof ScrimDrawable) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
deleted file mode 100644
index 0378123..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar;
-
-import static com.android.systemui.classifier.Classifier.NOTIFICATION_DRAG_DOWN;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ObjectAnimator;
-import android.animation.ValueAnimator;
-import android.content.Context;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewConfiguration;
-
-import com.android.systemui.ExpandHelper;
-import com.android.systemui.Gefingerpoken;
-import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
-import com.android.systemui.classifier.FalsingCollector;
-import com.android.systemui.plugins.FalsingManager;
-import com.android.systemui.statusbar.notification.row.ExpandableView;
-
-/**
- * A utility class to enable the downward swipe on the lockscreen to go to the full shade and expand
- * the notification where the drag started.
- */
-public class DragDownHelper implements Gefingerpoken {
-
- private static final float RUBBERBAND_FACTOR_EXPANDABLE = 0.5f;
- private static final float RUBBERBAND_FACTOR_STATIC = 0.15f;
-
- private static final int SPRING_BACK_ANIMATION_LENGTH_MS = 375;
-
- private int mMinDragDistance;
- private final FalsingManager mFalsingManager;
- private ExpandHelper.Callback mCallback;
- private float mInitialTouchX;
- private float mInitialTouchY;
- private boolean mDraggingDown;
- private final float mTouchSlop;
- private final float mSlopMultiplier;
- private DragDownCallback mDragDownCallback;
- private View mHost;
- private final int[] mTemp2 = new int[2];
- private boolean mDraggedFarEnough;
- private ExpandableView mStartingChild;
- private float mLastHeight;
- private FalsingCollector mFalsingCollector;
-
- public DragDownHelper(Context context, View host, ExpandHelper.Callback callback,
- DragDownCallback dragDownCallback, FalsingManager falsingManager,
- FalsingCollector falsingCollector) {
- mMinDragDistance = context.getResources().getDimensionPixelSize(
- R.dimen.keyguard_drag_down_min_distance);
- mFalsingManager = falsingManager;
- final ViewConfiguration configuration = ViewConfiguration.get(context);
- mTouchSlop = configuration.getScaledTouchSlop();
- mSlopMultiplier = configuration.getScaledAmbiguousGestureMultiplier();
- mCallback = callback;
- mDragDownCallback = dragDownCallback;
- mHost = host;
- mFalsingCollector = falsingCollector;
- }
-
- @Override
- public boolean onInterceptTouchEvent(MotionEvent event) {
- final float x = event.getX();
- final float y = event.getY();
-
- switch (event.getActionMasked()) {
- case MotionEvent.ACTION_DOWN:
- mDraggedFarEnough = false;
- mDraggingDown = false;
- mStartingChild = null;
- mInitialTouchY = y;
- mInitialTouchX = x;
- break;
-
- case MotionEvent.ACTION_MOVE:
- final float h = y - mInitialTouchY;
- // Adjust the touch slop if another gesture may be being performed.
- final float touchSlop =
- event.getClassification() == MotionEvent.CLASSIFICATION_AMBIGUOUS_GESTURE
- ? mTouchSlop * mSlopMultiplier
- : mTouchSlop;
- if (h > touchSlop && h > Math.abs(x - mInitialTouchX)) {
- mFalsingCollector.onNotificationStartDraggingDown();
- mDraggingDown = true;
- captureStartingChild(mInitialTouchX, mInitialTouchY);
- mInitialTouchY = y;
- mInitialTouchX = x;
- mDragDownCallback.onTouchSlopExceeded();
- return mStartingChild != null || mDragDownCallback.isDragDownAnywhereEnabled();
- }
- break;
- }
- return false;
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- if (!mDraggingDown) {
- return false;
- }
- final float x = event.getX();
- final float y = event.getY();
-
- switch (event.getActionMasked()) {
- case MotionEvent.ACTION_MOVE:
- mLastHeight = y - mInitialTouchY;
- captureStartingChild(mInitialTouchX, mInitialTouchY);
- if (mStartingChild != null) {
- handleExpansion(mLastHeight, mStartingChild);
- } else {
- mDragDownCallback.setEmptyDragAmount(mLastHeight);
- }
- if (mLastHeight > mMinDragDistance) {
- if (!mDraggedFarEnough) {
- mDraggedFarEnough = true;
- mDragDownCallback.onCrossedThreshold(true);
- }
- } else {
- if (mDraggedFarEnough) {
- mDraggedFarEnough = false;
- mDragDownCallback.onCrossedThreshold(false);
- }
- }
- return true;
- case MotionEvent.ACTION_UP:
- if (!mFalsingManager.isUnlockingDisabled() && mDragDownCallback.canDragDown()
- && !isFalseTouch()) {
- mDragDownCallback.onDraggedDown(mStartingChild, (int) (y - mInitialTouchY));
- if (mStartingChild == null) {
- cancelExpansion();
- } else {
- mCallback.setUserLockedChild(mStartingChild, false);
- mStartingChild = null;
- }
- mDraggingDown = false;
- } else {
- stopDragging();
- return false;
- }
- break;
- case MotionEvent.ACTION_CANCEL:
- stopDragging();
- return false;
- }
- return false;
- }
-
- private boolean isFalseTouch() {
- if (!mDragDownCallback.isFalsingCheckNeeded()) {
- return false;
- }
- return mFalsingManager.isFalseTouch(NOTIFICATION_DRAG_DOWN) || !mDraggedFarEnough;
- }
-
- private void captureStartingChild(float x, float y) {
- if (mStartingChild == null) {
- mStartingChild = findView(x, y);
- if (mStartingChild != null) {
- if (mDragDownCallback.isDragDownEnabledForView(mStartingChild)) {
- mCallback.setUserLockedChild(mStartingChild, true);
- } else {
- mStartingChild = null;
- }
- }
- }
- }
-
- private void handleExpansion(float heightDelta, ExpandableView child) {
- if (heightDelta < 0) {
- heightDelta = 0;
- }
- boolean expandable = child.isContentExpandable();
- float rubberbandFactor = expandable
- ? RUBBERBAND_FACTOR_EXPANDABLE
- : RUBBERBAND_FACTOR_STATIC;
- float rubberband = heightDelta * rubberbandFactor;
- if (expandable
- && (rubberband + child.getCollapsedHeight()) > child.getMaxContentHeight()) {
- float overshoot =
- (rubberband + child.getCollapsedHeight()) - child.getMaxContentHeight();
- overshoot *= (1 - RUBBERBAND_FACTOR_STATIC);
- rubberband -= overshoot;
- }
- child.setActualHeight((int) (child.getCollapsedHeight() + rubberband));
- }
-
- private void cancelExpansion(final ExpandableView child) {
- if (child.getActualHeight() == child.getCollapsedHeight()) {
- mCallback.setUserLockedChild(child, false);
- return;
- }
- ObjectAnimator anim = ObjectAnimator.ofInt(child, "actualHeight",
- child.getActualHeight(), child.getCollapsedHeight());
- anim.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
- anim.setDuration(SPRING_BACK_ANIMATION_LENGTH_MS);
- anim.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mCallback.setUserLockedChild(child, false);
- }
- });
- anim.start();
- }
-
- private void cancelExpansion() {
- ValueAnimator anim = ValueAnimator.ofFloat(mLastHeight, 0);
- anim.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
- anim.setDuration(SPRING_BACK_ANIMATION_LENGTH_MS);
- anim.addUpdateListener(animation -> {
- mDragDownCallback.setEmptyDragAmount((Float) animation.getAnimatedValue());
- });
- anim.start();
- }
-
- private void stopDragging() {
- mFalsingCollector.onNotificationStopDraggingDown();
- if (mStartingChild != null) {
- cancelExpansion(mStartingChild);
- mStartingChild = null;
- } else {
- cancelExpansion();
- }
- mDraggingDown = false;
- mDragDownCallback.onDragDownReset();
- }
-
- private ExpandableView findView(float x, float y) {
- mHost.getLocationOnScreen(mTemp2);
- x += mTemp2[0];
- y += mTemp2[1];
- return mCallback.getChildAtRawPosition(x, y);
- }
-
- public boolean isDraggingDown() {
- return mDraggingDown;
- }
-
- public boolean isDragDownEnabled() {
- return mDragDownCallback.isDragDownEnabledForView(null);
- }
-
- public interface DragDownCallback {
-
- /**
- * @return true if the interaction is accepted, false if it should be cancelled
- */
- boolean canDragDown();
-
- /** Call when a view has been dragged. */
- void onDraggedDown(View startingChild, int dragLengthY);
- void onDragDownReset();
-
- /**
- * The user has dragged either above or below the threshold
- * @param above whether he dragged above it
- */
- void onCrossedThreshold(boolean above);
- void onTouchSlopExceeded();
- void setEmptyDragAmount(float amount);
- boolean isFalsingCheckNeeded();
-
- /**
- * Is dragging down enabled on a given view
- * @param view The view to check or {@code null} to check if it's enabled at all
- */
- boolean isDragDownEnabledForView(ExpandableView view);
-
- /**
- * @return if drag down is enabled anywhere, not just on selected views.
- */
- boolean isDragDownAnywhereEnabled();
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java b/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java
index d96e1ba..ac6d9e8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java
@@ -92,4 +92,8 @@
public boolean isSmartspaceEnabled() {
return mFlagReader.isEnabled(R.bool.flag_smartspace);
}
+
+ public boolean isSmartspaceDedupingEnabled() {
+ return isSmartspaceEnabled() && mFlagReader.isEnabled(R.bool.flag_smartspace_deduping);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 5daee6c..91a0e6f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -33,7 +33,6 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
-import android.app.ActivityManager;
import android.app.IActivityManager;
import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
@@ -147,6 +146,7 @@
private long mChargingTimeRemaining;
private String mMessageToShowOnScreenOn;
protected int mLockScreenMode;
+ private boolean mInited;
private KeyguardUpdateMonitorCallback mUpdateMonitorCallback;
@@ -174,7 +174,9 @@
IBatteryStats iBatteryStats,
UserManager userManager,
@Main DelayableExecutor executor,
- FalsingManager falsingManager) {
+ FalsingManager falsingManager,
+ LockPatternUtils lockPatternUtils,
+ IActivityManager iActivityManager) {
mContext = context;
mBroadcastDispatcher = broadcastDispatcher;
mDevicePolicyManager = devicePolicyManager;
@@ -182,17 +184,26 @@
mStatusBarStateController = statusBarStateController;
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mDockManager = dockManager;
- mDockManager.addAlignmentStateListener(
- alignState -> mHandler.post(() -> handleAlignStateChanged(alignState)));
mWakeLock = new SettableWakeLock(
wakeLockBuilder.setTag("Doze:KeyguardIndication").build(), TAG);
mBatteryInfo = iBatteryStats;
mUserManager = userManager;
mExecutor = executor;
- mLockPatternUtils = new LockPatternUtils(context);
- mIActivityManager = ActivityManager.getService();
+ mLockPatternUtils = lockPatternUtils;
+ mIActivityManager = iActivityManager;
mFalsingManager = falsingManager;
+ }
+
+ /** Call this after construction to finish setting up the instance. */
+ public void init() {
+ if (mInited) {
+ return;
+ }
+ mInited = true;
+
+ mDockManager.addAlignmentStateListener(
+ alignState -> mHandler.post(() -> handleAlignStateChanged(alignState)));
mKeyguardUpdateMonitor.registerCallback(getKeyguardCallback());
mKeyguardUpdateMonitor.registerCallback(mTickReceiver);
mStatusBarStateController.addCallback(mStatusBarStateListener);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
new file mode 100644
index 0000000..12f569c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
@@ -0,0 +1,667 @@
+package com.android.systemui.statusbar
+
+import android.animation.Animator
+import android.animation.AnimatorListenerAdapter
+import android.animation.ObjectAnimator
+import android.animation.ValueAnimator
+import android.content.Context
+import android.content.res.Configuration
+import android.os.SystemClock
+import android.util.DisplayMetrics
+import android.util.MathUtils
+import android.view.MotionEvent
+import android.view.View
+import android.view.ViewConfiguration
+import androidx.annotation.VisibleForTesting
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent
+import com.android.systemui.ExpandHelper
+import com.android.systemui.Gefingerpoken
+import com.android.systemui.R
+import com.android.systemui.animation.Interpolators
+import com.android.systemui.classifier.Classifier
+import com.android.systemui.classifier.FalsingCollector
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.media.MediaHierarchyManager
+import com.android.systemui.plugins.ActivityStarter.OnDismissAction
+import com.android.systemui.plugins.FalsingManager
+import com.android.systemui.plugins.qs.QS
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
+import com.android.systemui.statusbar.notification.row.ExpandableView
+import com.android.systemui.statusbar.notification.stack.AmbientState
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
+import com.android.systemui.statusbar.phone.KeyguardBypassController
+import com.android.systemui.statusbar.phone.LockscreenGestureLogger
+import com.android.systemui.statusbar.phone.LockscreenGestureLogger.LockscreenUiEvent
+import com.android.systemui.statusbar.phone.NotificationPanelViewController
+import com.android.systemui.statusbar.phone.ScrimController
+import com.android.systemui.statusbar.phone.StatusBar
+import com.android.systemui.statusbar.policy.ConfigurationController
+import com.android.systemui.util.Utils
+import javax.inject.Inject
+
+private const val SPRING_BACK_ANIMATION_LENGTH_MS = 375L
+private const val RUBBERBAND_FACTOR_STATIC = 0.15f
+private const val RUBBERBAND_FACTOR_EXPANDABLE = 0.5f
+
+/**
+ * A class that controls the lockscreen to shade transition
+ */
+@SysUISingleton
+class LockscreenShadeTransitionController @Inject constructor(
+ private val statusBarStateController: SysuiStatusBarStateController,
+ private val lockscreenGestureLogger: LockscreenGestureLogger,
+ private val keyguardBypassController: KeyguardBypassController,
+ private val lockScreenUserManager: NotificationLockscreenUserManager,
+ private val falsingCollector: FalsingCollector,
+ private val ambientState: AmbientState,
+ private val displayMetrics: DisplayMetrics,
+ private val mediaHierarchyManager: MediaHierarchyManager,
+ private val scrimController: ScrimController,
+ private val featureFlags: FeatureFlags,
+ private val context: Context,
+ configurationController: ConfigurationController,
+ falsingManager: FalsingManager
+) {
+ private var useSplitShade: Boolean = false
+ private lateinit var nsslController: NotificationStackScrollLayoutController
+ lateinit var notificationPanelController: NotificationPanelViewController
+ lateinit var statusbar: StatusBar
+ lateinit var qS: QS
+
+ /**
+ * A handler that handles the next keyguard dismiss animation.
+ */
+ private var animationHandlerOnKeyguardDismiss: ((Long) -> Unit)? = null
+
+ /**
+ * The entry that was just dragged down on.
+ */
+ private var draggedDownEntry: NotificationEntry? = null
+
+ /**
+ * The current animator if any
+ */
+ @VisibleForTesting
+ internal var dragDownAnimator: ValueAnimator? = null
+
+ /**
+ * Distance that the full shade transition takes in order for scrim to fully transition to
+ * the shade (in alpha)
+ */
+ private var scrimTransitionDistance = 0
+
+ /**
+ * Distance that the full transition takes in order for us to fully transition to the shade
+ */
+ private var fullTransitionDistance = 0
+
+ /**
+ * Flag to make sure that the dragDownAmount is applied to the listeners even when in the
+ * locked down shade.
+ */
+ private var forceApplyAmount = false
+
+ /**
+ * A flag to suppress the default animation when unlocking in the locked down shade.
+ */
+ private var nextHideKeyguardNeedsNoAnimation = false
+
+ /**
+ * The touch helper responsible for the drag down animation.
+ */
+ val touchHelper = DragDownHelper(falsingManager, falsingCollector, this, context)
+
+ init {
+ updateResources()
+ configurationController.addCallback(object : ConfigurationController.ConfigurationListener {
+ override fun onConfigChanged(newConfig: Configuration?) {
+ updateResources()
+ touchHelper.updateResources(context)
+ }
+ })
+ }
+
+ private fun updateResources() {
+ scrimTransitionDistance = context.resources.getDimensionPixelSize(
+ R.dimen.lockscreen_shade_scrim_transition_distance)
+ fullTransitionDistance = context.resources.getDimensionPixelSize(
+ R.dimen.lockscreen_shade_qs_transition_distance)
+ useSplitShade = Utils.shouldUseSplitNotificationShade(featureFlags, context.resources)
+ }
+
+ fun setStackScroller(nsslController: NotificationStackScrollLayoutController) {
+ this.nsslController = nsslController
+ touchHelper.host = nsslController.view
+ touchHelper.expandCallback = nsslController.expandHelperCallback
+ }
+
+ /**
+ * Initialize the shelf controller such that clicks on it will expand the shade
+ */
+ fun bindController(notificationShelfController: NotificationShelfController) {
+ // Bind the click listener of the shelf to go to the full shade
+ notificationShelfController.setOnClickListener {
+ if (statusBarStateController.state == StatusBarState.KEYGUARD) {
+ statusbar.wakeUpIfDozing(SystemClock.uptimeMillis(), it, "SHADE_CLICK")
+ goToLockedShade(it)
+ }
+ }
+ }
+
+ /**
+ * @return true if the interaction is accepted, false if it should be cancelled
+ */
+ internal fun canDragDown(): Boolean {
+ return (statusBarStateController.state == StatusBarState.KEYGUARD ||
+ nsslController.isInLockedDownShade()) &&
+ qS.isFullyCollapsed
+ }
+
+ /**
+ * Called by the touch helper when when a gesture has completed all the way and released.
+ */
+ internal fun onDraggedDown(startingChild: View?, dragLengthY: Int) {
+ if (canDragDown()) {
+ if (nsslController.isInLockedDownShade()) {
+ statusBarStateController.setLeaveOpenOnKeyguardHide(true)
+ statusbar.dismissKeyguardThenExecute(OnDismissAction {
+ nextHideKeyguardNeedsNoAnimation = true
+ false
+ },
+ null /* cancelRunnable */, false /* afterKeyguardGone */)
+ } else {
+ lockscreenGestureLogger.write(
+ MetricsEvent.ACTION_LS_SHADE,
+ (dragLengthY / displayMetrics.density).toInt(),
+ 0 /* velocityDp */)
+ lockscreenGestureLogger.log(LockscreenUiEvent.LOCKSCREEN_PULL_SHADE_OPEN)
+ if (!ambientState.isDozing() || startingChild != null) {
+ // go to locked shade while animating the drag down amount from its current
+ // value
+ val animationHandler = { delay: Long ->
+ if (startingChild is ExpandableNotificationRow) {
+ startingChild.onExpandedByGesture(
+ true /* drag down is always an open */)
+ }
+ notificationPanelController.animateToFullShade(delay)
+ notificationPanelController.setTransitionToFullShadeAmount(0f,
+ true /* animated */, delay)
+
+ // Let's reset ourselves, ready for the next animation
+
+ // changing to shade locked will make isInLockDownShade true, so let's
+ // override that
+ forceApplyAmount = true
+ // Reset the behavior. At this point the animation is already started
+ dragDownAmount = 0f
+ forceApplyAmount = false
+ }
+ val cancelRunnable = Runnable { setDragDownAmountAnimated(0f) }
+ goToLockedShadeInternal(startingChild, animationHandler, cancelRunnable)
+ }
+ }
+ } else {
+ setDragDownAmountAnimated(0f)
+ }
+ }
+
+ /**
+ * Called by the touch helper when the drag down was aborted and should be reset.
+ */
+ internal fun onDragDownReset() {
+ nsslController.setDimmed(true /* dimmed */, true /* animated */)
+ nsslController.resetScrollPosition()
+ nsslController.resetCheckSnoozeLeavebehind()
+ setDragDownAmountAnimated(0f)
+ }
+
+ /**
+ * The user has dragged either above or below the threshold which changes the dimmed state.
+ * @param above whether they dragged above it
+ */
+ internal fun onCrossedThreshold(above: Boolean) {
+ nsslController.setDimmed(!above /* dimmed */, true /* animate */)
+ }
+
+ /**
+ * Called by the touch helper when the drag down was started
+ */
+ internal fun onDragDownStarted() {
+ nsslController.cancelLongPress()
+ nsslController.checkSnoozeLeavebehind()
+ dragDownAnimator?.cancel()
+ }
+
+ /**
+ * Do we need a falsing check currently?
+ */
+ internal val isFalsingCheckNeeded: Boolean
+ get() = statusBarStateController.state == StatusBarState.KEYGUARD
+
+ /**
+ * Is dragging down enabled on a given view
+ * @param view The view to check or `null` to check if it's enabled at all
+ */
+ internal fun isDragDownEnabledForView(view: ExpandableView?): Boolean {
+ if (isDragDownAnywhereEnabled) {
+ return true
+ }
+ if (nsslController.isInLockedDownShade()) {
+ if (view == null) {
+ // Dragging down is allowed in general
+ return true
+ }
+ if (view is ExpandableNotificationRow) {
+ // Only drag down on sensitive views, otherwise the ExpandHelper will take this
+ return view.entry.isSensitive
+ }
+ }
+ return false
+ }
+
+ /**
+ * @return if drag down is enabled anywhere, not just on selected views.
+ */
+ internal val isDragDownAnywhereEnabled: Boolean
+ get() = (statusBarStateController.getState() == StatusBarState.KEYGUARD &&
+ !keyguardBypassController.bypassEnabled &&
+ qS.isFullyCollapsed)
+
+ /**
+ * The amount in pixels that the user has dragged down.
+ */
+ internal var dragDownAmount = 0f
+ set(value) {
+ if (field != value || forceApplyAmount) {
+ field = value
+ if (!nsslController.isInLockedDownShade() || forceApplyAmount) {
+ nsslController.setTransitionToFullShadeAmount(field)
+ notificationPanelController.setTransitionToFullShadeAmount(field,
+ false /* animate */, 0 /* delay */)
+ mediaHierarchyManager.setTransitionToFullShadeAmount(field)
+ val scrimProgress = MathUtils.saturate(field / scrimTransitionDistance)
+ scrimController.setTransitionToFullShadeProgress(scrimProgress)
+ // TODO: appear qs also in split shade
+ val qsAmount = if (useSplitShade) 0f else field
+ qS.setTransitionToFullShadeAmount(qsAmount, false /* animate */)
+ }
+ }
+ }
+
+ private fun setDragDownAmountAnimated(
+ target: Float,
+ delay: Long = 0,
+ endlistener: (() -> Unit)? = null
+ ) {
+ val dragDownAnimator = ValueAnimator.ofFloat(dragDownAmount, target)
+ dragDownAnimator.interpolator = Interpolators.FAST_OUT_SLOW_IN
+ dragDownAnimator.duration = SPRING_BACK_ANIMATION_LENGTH_MS
+ dragDownAnimator.addUpdateListener { animation: ValueAnimator ->
+ dragDownAmount = animation.animatedValue as Float
+ }
+ if (delay > 0) {
+ dragDownAnimator.startDelay = delay
+ }
+ if (endlistener != null) {
+ dragDownAnimator.addListener(object : AnimatorListenerAdapter() {
+ override fun onAnimationEnd(animation: Animator?) {
+ endlistener.invoke()
+ }
+ })
+ }
+ dragDownAnimator.start()
+ this.dragDownAnimator = dragDownAnimator
+ }
+
+ /**
+ * Animate appear the drag down amount.
+ */
+ private fun animateAppear(delay: Long = 0) {
+ // changing to shade locked will make isInLockDownShade true, so let's override
+ // that
+ forceApplyAmount = true
+
+ // we set the value initially to 1 pixel, since that will make sure we're
+ // transitioning to the full shade. this is important to avoid flickering,
+ // as the below animation only starts once the shade is unlocked, which can
+ // be a couple of frames later. if we're setting it to 0, it will use the
+ // default inset and therefore flicker
+ dragDownAmount = 1f
+ setDragDownAmountAnimated(fullTransitionDistance.toFloat(), delay = delay) {
+ // End listener:
+ // Reset
+ dragDownAmount = 0f
+ forceApplyAmount = false
+ }
+ }
+
+ /**
+ * Ask this controller to go to the locked shade, changing the state change and doing
+ * an animation, where the qs appears from 0 from the top
+ *
+ * If secure with redaction: Show bouncer, go to unlocked shade.
+ * If secure without redaction or no security: Go to [StatusBarState.SHADE_LOCKED].
+ *
+ * @param expandView The view to expand after going to the shade
+ * @param needsQSAnimation if this needs the quick settings to slide in from the top or if
+ * that's already handled separately
+ */
+ @JvmOverloads
+ fun goToLockedShade(expandedView: View?, needsQSAnimation: Boolean = true) {
+ if (statusBarStateController.state == StatusBarState.KEYGUARD) {
+ val animationHandler: ((Long) -> Unit)?
+ if (needsQSAnimation) {
+ // Let's use the default animation
+ animationHandler = null
+ } else {
+ // Let's only animate notifications
+ animationHandler = { delay: Long ->
+ notificationPanelController.animateToFullShade(delay)
+ }
+ }
+ goToLockedShadeInternal(expandedView, animationHandler,
+ cancelAction = null)
+ }
+ }
+
+ /**
+ * If secure with redaction: Show bouncer, go to unlocked shade.
+ *
+ * If secure without redaction or no security: Go to [StatusBarState.SHADE_LOCKED].
+ *
+ * @param expandView The view to expand after going to the shade.
+ * @param animationHandler The handler which performs the go to full shade animation. If null,
+ * the default handler will do the animation, otherwise the caller is
+ * responsible for the animation. The input value is a Long for the
+ * delay for the animation.
+ * @param cancelAction The runnable to invoke when the transition is aborted. This happens if
+ * the user goes to the bouncer and goes back.
+ */
+ private fun goToLockedShadeInternal(
+ expandView: View?,
+ animationHandler: ((Long) -> Unit)? = null,
+ cancelAction: Runnable? = null
+ ) {
+ if (statusbar.isShadeDisabled) {
+ cancelAction?.run()
+ return
+ }
+ var userId: Int = lockScreenUserManager.getCurrentUserId()
+ var entry: NotificationEntry? = null
+ if (expandView is ExpandableNotificationRow) {
+ entry = expandView.entry
+ entry.setUserExpanded(true /* userExpanded */, true /* allowChildExpansion */)
+ // Indicate that the group expansion is changing at this time -- this way the group
+ // and children backgrounds / divider animations will look correct.
+ entry.setGroupExpansionChanging(true)
+ userId = entry.sbn.userId
+ }
+ var fullShadeNeedsBouncer = (!lockScreenUserManager.userAllowsPrivateNotificationsInPublic(
+ lockScreenUserManager.getCurrentUserId()) ||
+ !lockScreenUserManager.shouldShowLockscreenNotifications() ||
+ falsingCollector.shouldEnforceBouncer())
+ if (keyguardBypassController.bypassEnabled) {
+ fullShadeNeedsBouncer = false
+ }
+ if (lockScreenUserManager.isLockscreenPublicMode(userId) && fullShadeNeedsBouncer) {
+ statusBarStateController.setLeaveOpenOnKeyguardHide(true)
+ var onDismissAction: OnDismissAction? = null
+ if (animationHandler != null) {
+ onDismissAction = OnDismissAction {
+ // We're waiting on keyguard to hide before triggering the action,
+ // as that will make the animation work properly
+ animationHandlerOnKeyguardDismiss = animationHandler
+ false
+ }
+ }
+ val cancelHandler = Runnable {
+ draggedDownEntry?.apply {
+ setUserLocked(false)
+ notifyHeightChanged(false /* needsAnimation */)
+ draggedDownEntry = null
+ }
+ cancelAction?.run()
+ }
+ statusbar.showBouncerWithDimissAndCancelIfKeyguard(onDismissAction, cancelHandler)
+ draggedDownEntry = entry
+ } else {
+ statusBarStateController.setState(StatusBarState.SHADE_LOCKED)
+ // This call needs to be after updating the shade state since otherwise
+ // the scrimstate resets too early
+ if (animationHandler != null) {
+ animationHandler.invoke(0 /* delay */)
+ } else {
+ performDefaultGoToFullShadeAnimation(0)
+ }
+ }
+ }
+
+ /**
+ * Notify this handler that the keyguard was just dismissed and that a animation to
+ * the full shade should happen.
+ */
+ fun onHideKeyguard(delay: Long) {
+ if (animationHandlerOnKeyguardDismiss != null) {
+ animationHandlerOnKeyguardDismiss!!.invoke(delay)
+ animationHandlerOnKeyguardDismiss = null
+ } else {
+ if (nextHideKeyguardNeedsNoAnimation) {
+ nextHideKeyguardNeedsNoAnimation = false
+ } else {
+ performDefaultGoToFullShadeAnimation(delay)
+ }
+ }
+ draggedDownEntry?.apply {
+ setUserLocked(false)
+ draggedDownEntry = null
+ }
+ }
+
+ /**
+ * Perform the default appear animation when going to the full shade. This is called when
+ * not triggered by gestures, e.g. when clicking on the shelf or expand button.
+ */
+ private fun performDefaultGoToFullShadeAnimation(delay: Long) {
+ notificationPanelController.animateToFullShade(delay)
+ animateAppear(delay)
+ }
+}
+
+/**
+ * A utility class to enable the downward swipe on the lockscreen to go to the full shade and expand
+ * the notification where the drag started.
+ */
+class DragDownHelper(
+ private val falsingManager: FalsingManager,
+ private val falsingCollector: FalsingCollector,
+ private val dragDownCallback: LockscreenShadeTransitionController,
+ context: Context
+) : Gefingerpoken {
+
+ private var dragDownAmountOnStart = 0.0f
+ lateinit var expandCallback: ExpandHelper.Callback
+ lateinit var host: View
+
+ private var minDragDistance = 0
+ private var initialTouchX = 0f
+ private var initialTouchY = 0f
+ private var touchSlop = 0f
+ private var slopMultiplier = 0f
+ private val temp2 = IntArray(2)
+ private var draggedFarEnough = false
+ private var startingChild: ExpandableView? = null
+ private var lastHeight = 0f
+ var isDraggingDown = false
+ private set
+
+ private val isFalseTouch: Boolean
+ get() {
+ return if (!dragDownCallback.isFalsingCheckNeeded) {
+ false
+ } else {
+ falsingManager.isFalseTouch(Classifier.NOTIFICATION_DRAG_DOWN) || !draggedFarEnough
+ }
+ }
+
+ val isDragDownEnabled: Boolean
+ get() = dragDownCallback.isDragDownEnabledForView(null)
+
+ init {
+ updateResources(context)
+ }
+
+ fun updateResources(context: Context) {
+ minDragDistance = context.resources.getDimensionPixelSize(
+ R.dimen.keyguard_drag_down_min_distance)
+ val configuration = ViewConfiguration.get(context)
+ touchSlop = configuration.scaledTouchSlop.toFloat()
+ slopMultiplier = configuration.scaledAmbiguousGestureMultiplier
+ }
+
+ override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
+ val x = event.x
+ val y = event.y
+ when (event.actionMasked) {
+ MotionEvent.ACTION_DOWN -> {
+ draggedFarEnough = false
+ isDraggingDown = false
+ startingChild = null
+ initialTouchY = y
+ initialTouchX = x
+ }
+ MotionEvent.ACTION_MOVE -> {
+ val h = y - initialTouchY
+ // Adjust the touch slop if another gesture may be being performed.
+ val touchSlop = if (event.classification
+ == MotionEvent.CLASSIFICATION_AMBIGUOUS_GESTURE)
+ touchSlop * slopMultiplier
+ else
+ touchSlop
+ if (h > touchSlop && h > Math.abs(x - initialTouchX)) {
+ falsingCollector.onNotificationStartDraggingDown()
+ isDraggingDown = true
+ captureStartingChild(initialTouchX, initialTouchY)
+ initialTouchY = y
+ initialTouchX = x
+ dragDownCallback.onDragDownStarted()
+ dragDownAmountOnStart = dragDownCallback.dragDownAmount
+ return startingChild != null || dragDownCallback.isDragDownAnywhereEnabled
+ }
+ }
+ }
+ return false
+ }
+
+ override fun onTouchEvent(event: MotionEvent): Boolean {
+ if (!isDraggingDown) {
+ return false
+ }
+ val x = event.x
+ val y = event.y
+ when (event.actionMasked) {
+ MotionEvent.ACTION_MOVE -> {
+ lastHeight = y - initialTouchY
+ captureStartingChild(initialTouchX, initialTouchY)
+ dragDownCallback.dragDownAmount = lastHeight + dragDownAmountOnStart
+ if (startingChild != null) {
+ handleExpansion(lastHeight, startingChild!!)
+ }
+ if (lastHeight > minDragDistance) {
+ if (!draggedFarEnough) {
+ draggedFarEnough = true
+ dragDownCallback.onCrossedThreshold(true)
+ }
+ } else {
+ if (draggedFarEnough) {
+ draggedFarEnough = false
+ dragDownCallback.onCrossedThreshold(false)
+ }
+ }
+ return true
+ }
+ MotionEvent.ACTION_UP -> if (!falsingManager.isUnlockingDisabled && !isFalseTouch &&
+ dragDownCallback.canDragDown()) {
+ dragDownCallback.onDraggedDown(startingChild, (y - initialTouchY).toInt())
+ if (startingChild != null) {
+ expandCallback.setUserLockedChild(startingChild, false)
+ startingChild = null
+ }
+ isDraggingDown = false
+ } else {
+ stopDragging()
+ return false
+ }
+ MotionEvent.ACTION_CANCEL -> {
+ stopDragging()
+ return false
+ }
+ }
+ return false
+ }
+
+ private fun captureStartingChild(x: Float, y: Float) {
+ if (startingChild == null) {
+ startingChild = findView(x, y)
+ if (startingChild != null) {
+ if (dragDownCallback.isDragDownEnabledForView(startingChild)) {
+ expandCallback.setUserLockedChild(startingChild, true)
+ } else {
+ startingChild = null
+ }
+ }
+ }
+ }
+
+ private fun handleExpansion(heightDelta: Float, child: ExpandableView) {
+ var hDelta = heightDelta
+ if (hDelta < 0) {
+ hDelta = 0f
+ }
+ val expandable = child.isContentExpandable
+ val rubberbandFactor = if (expandable) {
+ RUBBERBAND_FACTOR_EXPANDABLE
+ } else {
+ RUBBERBAND_FACTOR_STATIC
+ }
+ var rubberband = hDelta * rubberbandFactor
+ if (expandable && rubberband + child.collapsedHeight > child.maxContentHeight) {
+ var overshoot = rubberband + child.collapsedHeight - child.maxContentHeight
+ overshoot *= 1 - RUBBERBAND_FACTOR_STATIC
+ rubberband -= overshoot
+ }
+ child.actualHeight = (child.collapsedHeight + rubberband).toInt()
+ }
+
+ private fun cancelChildExpansion(child: ExpandableView) {
+ if (child.actualHeight == child.collapsedHeight) {
+ expandCallback.setUserLockedChild(child, false)
+ return
+ }
+ val anim = ObjectAnimator.ofInt(child, "actualHeight",
+ child.actualHeight, child.collapsedHeight)
+ anim.interpolator = Interpolators.FAST_OUT_SLOW_IN
+ anim.duration = SPRING_BACK_ANIMATION_LENGTH_MS
+ anim.addListener(object : AnimatorListenerAdapter() {
+ override fun onAnimationEnd(animation: Animator) {
+ expandCallback.setUserLockedChild(child, false)
+ }
+ })
+ anim.start()
+ }
+
+ private fun stopDragging() {
+ falsingCollector.onNotificationStopDraggingDown()
+ if (startingChild != null) {
+ cancelChildExpansion(startingChild!!)
+ startingChild = null
+ }
+ isDraggingDown = false
+ dragDownCallback.onDragDownReset()
+ }
+
+ private fun findView(x: Float, y: Float): ExpandableView? {
+ host.getLocationOnScreen(temp2)
+ return expandCallback.getChildAtRawPosition(x + temp2[0], y + temp2[1])
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java
index ebf7c2d..9a1a144 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java
@@ -50,6 +50,12 @@
void addUserChangedListener(UserChangedListener listener);
/**
+ * Registers a [KeyguardNotificationSuppressor] that will be consulted during
+ * {@link #shouldShowOnKeyguard(NotificationEntry)}
+ */
+ void addKeyguardNotificationSuppressor(KeyguardNotificationSuppressor suppressor);
+
+ /**
* Removes a listener previously registered with
* {@link #addUserChangedListener(UserChangedListener)}
*/
@@ -88,4 +94,9 @@
default void onUserChanged(int userId) {}
default void onCurrentProfilesChanged(SparseArray<UserInfo> currentProfiles) {}
}
+
+ /** Used to hide notifications on the lockscreen */
+ interface KeyguardNotificationSuppressor {
+ boolean shouldSuppressOnKeyguard(NotificationEntry entry);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
index 7eb921b..e7e9404 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
@@ -98,6 +98,7 @@
private LockPatternUtils mLockPatternUtils;
protected KeyguardManager mKeyguardManager;
private int mState = StatusBarState.SHADE;
+ private List<KeyguardNotificationSuppressor> mKeyguardSuppressors = new ArrayList<>();
protected final BroadcastReceiver mAllUsersReceiver = new BroadcastReceiver() {
@Override
@@ -343,6 +344,11 @@
Log.wtf(TAG, "mEntryManager was null!", new Throwable());
return false;
}
+ for (int i = 0; i < mKeyguardSuppressors.size(); i++) {
+ if (mKeyguardSuppressors.get(i).shouldSuppressOnKeyguard(entry)) {
+ return false;
+ }
+ }
boolean exceedsPriorityThreshold;
if (hideSilentNotificationsOnLockscreen()) {
exceedsPriorityThreshold =
@@ -621,6 +627,11 @@
}
@Override
+ public void addKeyguardNotificationSuppressor(KeyguardNotificationSuppressor suppressor) {
+ mKeyguardSuppressors.add(suppressor);
+ }
+
+ @Override
public void removeUserChangedListener(UserChangedListener listener) {
mListeners.remove(listener);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
index 2726488..f99436f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
@@ -250,7 +250,8 @@
@Override
public void onSmartspaceMediaDataLoaded(@NonNull String key,
- @NonNull SmartspaceTarget data) {
+ @NonNull SmartspaceTarget data, boolean shouldPrioritize) {
+
}
@Override
@@ -323,7 +324,8 @@
@Override
public void onSmartspaceMediaDataLoaded(@NonNull String key,
- @NonNull SmartspaceTarget data) {
+ @NonNull SmartspaceTarget data, boolean shouldPrioritize) {
+
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index e49ca13..b93da4b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -336,8 +336,13 @@
ActivatableNotificationView anv =
(ActivatableNotificationView) child;
+ final boolean isUnlockedHeadsUp = !mAmbientState.isOnKeyguard()
+ && !mAmbientState.isShadeExpanded()
+ && child instanceof ExpandableView
+ && ((ExpandableNotificationRow) child).isHeadsUp();
if (viewStart < shelfStart
&& !mHostLayoutController.isViewAffectedBySwipe(anv)
+ && !isUnlockedHeadsUp
&& !mAmbientState.isPulsing()
&& !mAmbientState.isDozing()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt b/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt
index 84465a8..9765ace 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt
@@ -42,7 +42,6 @@
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone
import com.android.systemui.statusbar.phone.KeyguardBypassController
-import com.android.systemui.statusbar.phone.ShadeController
import javax.inject.Inject
import kotlin.math.max
@@ -59,6 +58,7 @@
private val roundnessManager: NotificationRoundnessManager,
private val statusBarStateController: StatusBarStateController,
private val falsingManager: FalsingManager,
+ private val lockscreenShadeTransitionController: LockscreenShadeTransitionController,
private val falsingCollector: FalsingCollector
) : Gefingerpoken {
companion object {
@@ -66,7 +66,6 @@
private val SPRING_BACK_ANIMATION_LENGTH_MS = 375
}
private val mPowerManager: PowerManager?
- private lateinit var shadeController: ShadeController
private val mMinDragDistance: Int
private var mInitialTouchX: Float = 0.0f
@@ -95,7 +94,7 @@
var leavingLockscreen: Boolean = false
private set
private val mTouchSlop: Float
- private lateinit var expansionCallback: ExpansionCallback
+ private lateinit var overStretchHandler: OverStretchHandler
private lateinit var stackScrollerController: NotificationStackScrollLayoutController
private val mTemp2 = IntArray(2)
private var mDraggedFarEnough: Boolean = false
@@ -103,7 +102,7 @@
private var mPulsing: Boolean = false
var isWakingToShadeLocked: Boolean = false
private set
- private var mEmptyDragAmount: Float = 0.0f
+ private var overStretchAmount: Float = 0.0f
private var mWakeUpHeight: Float = 0.0f
private var mReachedWakeUpHeight: Boolean = false
private var velocityTracker: VelocityTracker? = null
@@ -215,6 +214,7 @@
private fun finishExpansion() {
resetClock()
+ val startingChild = mStartingChild
if (mStartingChild != null) {
setUserLocked(mStartingChild!!, false)
mStartingChild = null
@@ -225,7 +225,8 @@
mPowerManager!!.wakeUp(SystemClock.uptimeMillis(), WAKE_REASON_GESTURE,
"com.android.systemui:PULSEDRAG")
}
- shadeController.goToLockedShade(mStartingChild)
+ lockscreenShadeTransitionController.goToLockedShade(startingChild,
+ needsQSAnimation = false)
leavingLockscreen = true
isExpanding = false
if (mStartingChild is ExpandableNotificationRow) {
@@ -252,8 +253,8 @@
true /* increaseSpeed */)
expansionHeight = max(mWakeUpHeight, expansionHeight)
}
- val emptyDragAmount = wakeUpCoordinator.setPulseHeight(expansionHeight)
- setEmptyDragAmount(emptyDragAmount * RUBBERBAND_FACTOR_STATIC)
+ val dragDownAmount = wakeUpCoordinator.setPulseHeight(expansionHeight)
+ setOverStretchAmount(dragDownAmount)
}
private fun captureStartingChild(x: Float, y: Float) {
@@ -265,9 +266,9 @@
}
}
- private fun setEmptyDragAmount(amount: Float) {
- mEmptyDragAmount = amount
- expansionCallback.setEmptyDragAmount(amount)
+ private fun setOverStretchAmount(amount: Float) {
+ overStretchAmount = amount
+ overStretchHandler.setOverStretchAmount(amount)
}
private fun reset(child: ExpandableView) {
@@ -294,10 +295,12 @@
}
private fun resetClock() {
- val anim = ValueAnimator.ofFloat(mEmptyDragAmount, 0f)
+ val anim = ValueAnimator.ofFloat(overStretchAmount, 0f)
anim.interpolator = Interpolators.FAST_OUT_SLOW_IN
anim.duration = SPRING_BACK_ANIMATION_LENGTH_MS.toLong()
- anim.addUpdateListener { animation -> setEmptyDragAmount(animation.animatedValue as Float) }
+ anim.addUpdateListener {
+ animation -> setOverStretchAmount(animation.animatedValue as Float)
+ }
anim.start()
}
@@ -329,11 +332,9 @@
fun setUp(
stackScrollerController: NotificationStackScrollLayoutController,
- expansionCallback: ExpansionCallback,
- shadeController: ShadeController
+ overStrechHandler: OverStretchHandler
) {
- this.expansionCallback = expansionCallback
- this.shadeController = shadeController
+ this.overStretchHandler = overStrechHandler
this.stackScrollerController = stackScrollerController
}
@@ -345,7 +346,11 @@
isWakingToShadeLocked = false
}
- interface ExpansionCallback {
- fun setEmptyDragAmount(amount: Float)
+ interface OverStretchHandler {
+
+ /**
+ * Set the overstretch amount in pixels This will be rubberbanded later
+ */
+ fun setOverStretchAmount(amount: Float)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
index ce60c85..71546ae 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
@@ -106,8 +106,17 @@
return view
}
+ fun requestSmartspaceUpdate() {
+ session?.requestSmartspaceUpdate()
+ }
+
private fun buildView(parent: ViewGroup) {
- if (plugin == null || this::view.isInitialized) {
+ if (plugin == null) {
+ return
+ }
+ if (this::view.isInitialized) {
+ // Due to some oddities with a singleton smartspace view, allow reparenting
+ (view.getParent() as ViewGroup?)?.removeView(view)
return
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/DynamicPrivacyController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/DynamicPrivacyController.java
index 9482c17..a0ccd57 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/DynamicPrivacyController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/DynamicPrivacyController.java
@@ -19,6 +19,8 @@
import android.annotation.Nullable;
import android.util.ArraySet;
+import androidx.annotation.VisibleForTesting;
+
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
@@ -76,8 +78,9 @@
}
}
- private boolean isDynamicPrivacyEnabled() {
- return !mLockscreenUserManager.shouldHideNotifications(
+ @VisibleForTesting
+ boolean isDynamicPrivacyEnabled() {
+ return !mLockscreenUserManager.userAllowsPrivateNotificationsInPublic(
mLockscreenUserManager.getCurrentUserId());
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
index 13a8661..1ab2a9e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
@@ -46,8 +46,9 @@
import com.android.systemui.statusbar.NotificationRemoveInterceptor;
import com.android.systemui.statusbar.NotificationUiAdjustment;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.collection.NotificationRankingManager;
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder;
+import com.android.systemui.statusbar.notification.collection.legacy.LegacyNotificationRanker;
+import com.android.systemui.statusbar.notification.collection.legacy.LegacyNotificationRankerStub;
import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
@@ -138,12 +139,11 @@
private final LeakDetector mLeakDetector;
private final List<NotifCollectionListener> mNotifCollectionListeners = new ArrayList<>();
- private final KeyguardEnvironment mKeyguardEnvironment;
private final NotificationGroupManagerLegacy mGroupManager;
- private final Lazy<NotificationRankingManager> mRankingManager;
private final FeatureFlags mFeatureFlags;
private final ForegroundServiceDismissalFeatureController mFgsFeatureController;
+ private LegacyNotificationRanker mRanker = new LegacyNotificationRankerStub();
private NotificationPresenter mPresenter;
private RankingMap mLatestRankingMap;
@@ -200,8 +200,6 @@
public NotificationEntryManager(
NotificationEntryManagerLogger logger,
NotificationGroupManagerLegacy groupManager,
- Lazy<NotificationRankingManager> rankingManager,
- KeyguardEnvironment keyguardEnvironment,
FeatureFlags featureFlags,
Lazy<NotificationRowBinder> notificationRowBinderLazy,
Lazy<NotificationRemoteInputManager> notificationRemoteInputManagerLazy,
@@ -211,8 +209,6 @@
) {
mLogger = logger;
mGroupManager = groupManager;
- mRankingManager = rankingManager;
- mKeyguardEnvironment = keyguardEnvironment;
mFeatureFlags = featureFlags;
mNotificationRowBinderLazy = notificationRowBinderLazy;
mRemoteInputManagerLazy = notificationRemoteInputManagerLazy;
@@ -226,6 +222,10 @@
notificationListener.addNotificationHandler(mNotifListener);
}
+ public void setRanker(LegacyNotificationRanker ranker) {
+ mRanker = ranker;
+ }
+
/** Adds a {@link NotificationEntryListener}. */
public void addNotificationEntryListener(NotificationEntryListener listener) {
mNotificationEntryListeners.add(listener);
@@ -419,7 +419,7 @@
mActiveNotifications.put(entry.getKey(), entry);
mGroupManager.onEntryAdded(entry);
- updateRankingAndSort(mRankingManager.get().getRankingMap(), "addEntryInternalInternal");
+ updateRankingAndSort(mRanker.getRankingMap(), "addEntryInternalInternal");
}
/**
@@ -698,13 +698,6 @@
updateNotifications("updateNotificationInternal");
- if (DEBUG) {
- // Is this for you?
- boolean isForCurrentUser = mKeyguardEnvironment
- .isNotificationForCurrentProfiles(notification);
- Log.d(TAG, "notification is " + (isForCurrentUser ? "" : "not ") + "for you");
- }
-
for (NotificationEntryListener listener : mNotificationEntryListeners) {
listener.onPostEntryUpdated(entry);
}
@@ -862,8 +855,7 @@
final int len = mActiveNotifications.size();
for (int i = 0; i < len; i++) {
NotificationEntry entry = mActiveNotifications.valueAt(i);
- final StatusBarNotification sbn = entry.getSbn();
- if (!mKeyguardEnvironment.isNotificationForCurrentProfiles(sbn)) {
+ if (!mRanker.isNotificationForCurrentProfiles(entry)) {
continue;
}
filtered.add(entry);
@@ -886,13 +878,13 @@
/** Resorts / filters the current notification set with the current RankingMap */
public void reapplyFilterAndSort(String reason) {
- updateRankingAndSort(mRankingManager.get().getRankingMap(), reason);
+ updateRankingAndSort(mRanker.getRankingMap(), reason);
}
/** Calls to NotificationRankingManager and updates mSortedAndFiltered */
private void updateRankingAndSort(@NonNull RankingMap rankingMap, String reason) {
mSortedAndFiltered.clear();
- mSortedAndFiltered.addAll(mRankingManager.get().updateRanking(
+ mSortedAndFiltered.addAll(mRanker.updateRanking(
rankingMap, mActiveNotifications.values(), reason));
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java
index f21771a..1940cb2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java
@@ -27,14 +27,13 @@
import android.service.notification.StatusBarNotification;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.Dependency;
import com.android.systemui.ForegroundServiceController;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.media.MediaFeatureFlag;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
+import com.android.systemui.statusbar.notification.NotificationEntryManager.KeyguardEnvironment;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.phone.ShadeController;
import javax.inject.Inject;
@@ -46,68 +45,43 @@
public class NotificationFilter {
private final StatusBarStateController mStatusBarStateController;
+ private final KeyguardEnvironment mKeyguardEnvironment;
+ private final ForegroundServiceController mForegroundServiceController;
+ private final NotificationLockscreenUserManager mUserManager;
private final Boolean mIsMediaFlagEnabled;
- private NotificationEntryManager.KeyguardEnvironment mEnvironment;
- private ShadeController mShadeController;
- private ForegroundServiceController mFsc;
- private NotificationLockscreenUserManager mUserManager;
-
@Inject
public NotificationFilter(
StatusBarStateController statusBarStateController,
+ KeyguardEnvironment keyguardEnvironment,
+ ForegroundServiceController foregroundServiceController,
+ NotificationLockscreenUserManager userManager,
MediaFeatureFlag mediaFeatureFlag) {
mStatusBarStateController = statusBarStateController;
+ mKeyguardEnvironment = keyguardEnvironment;
+ mForegroundServiceController = foregroundServiceController;
+ mUserManager = userManager;
mIsMediaFlagEnabled = mediaFeatureFlag.getEnabled();
}
- private NotificationEntryManager.KeyguardEnvironment getEnvironment() {
- if (mEnvironment == null) {
- mEnvironment = Dependency.get(NotificationEntryManager.KeyguardEnvironment.class);
- }
- return mEnvironment;
- }
-
- private ShadeController getShadeController() {
- if (mShadeController == null) {
- mShadeController = Dependency.get(ShadeController.class);
- }
- return mShadeController;
- }
-
- private ForegroundServiceController getFsc() {
- if (mFsc == null) {
- mFsc = Dependency.get(ForegroundServiceController.class);
- }
- return mFsc;
- }
-
- private NotificationLockscreenUserManager getUserManager() {
- if (mUserManager == null) {
- mUserManager = Dependency.get(NotificationLockscreenUserManager.class);
- }
- return mUserManager;
- }
-
-
/**
* @return true if the provided notification should NOT be shown right now.
*/
public boolean shouldFilterOut(NotificationEntry entry) {
final StatusBarNotification sbn = entry.getSbn();
- if (!(getEnvironment().isDeviceProvisioned()
+ if (!(mKeyguardEnvironment.isDeviceProvisioned()
|| showNotificationEvenIfUnprovisioned(sbn))) {
return true;
}
- if (!getEnvironment().isNotificationForCurrentProfiles(sbn)) {
+ if (!mKeyguardEnvironment.isNotificationForCurrentProfiles(sbn)) {
return true;
}
- if (getUserManager().isLockscreenPublicMode(sbn.getUserId())
+ if (mUserManager.isLockscreenPublicMode(sbn.getUserId())
&& (sbn.getNotification().visibility == Notification.VISIBILITY_SECRET
- || getUserManager().shouldHideNotifications(sbn.getUserId())
- || getUserManager().shouldHideNotifications(sbn.getKey()))) {
+ || mUserManager.shouldHideNotifications(sbn.getUserId())
+ || mUserManager.shouldHideNotifications(sbn.getKey()))) {
return true;
}
@@ -123,8 +97,8 @@
return true;
}
- if (getFsc().isDisclosureNotification(sbn)
- && !getFsc().isDisclosureNeededForUser(sbn.getUserId())) {
+ if (mForegroundServiceController.isDisclosureNotification(sbn)
+ && !mForegroundServiceController.isDisclosureNeededForUser(sbn.getUserId())) {
// this is a foreground-service disclosure for a user that does not need to show one
return true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
index 6b96ee4..8ae31cb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
@@ -185,6 +185,11 @@
mBuildListener = buildListener;
}
+ /** @see NotifPipeline#getEntry(String) () */
+ NotificationEntry getEntry(String key) {
+ return mNotificationSet.get(key);
+ }
+
/** @see NotifPipeline#getAllNotifs() */
Collection<NotificationEntry> getAllNotifs() {
Assert.isMainThread();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifPipeline.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifPipeline.java
index a1844ff..47939f0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifPipeline.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifPipeline.java
@@ -16,6 +16,8 @@
package com.android.systemui.statusbar.notification.collection;
+import androidx.annotation.Nullable;
+
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeFinalizeFilterListener;
import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener;
@@ -89,6 +91,7 @@
*
* The returned collection is read-only, unsorted, unfiltered, and ungrouped.
*/
+ @Override
public Collection<NotificationEntry> getAllNotifs() {
return mNotifCollection.getAllNotifs();
}
@@ -99,6 +102,14 @@
}
/**
+ * Returns the NotificationEntry associated with [key].
+ */
+ @Nullable
+ public NotificationEntry getEntry(String key) {
+ return mNotifCollection.getEntry(key);
+ }
+
+ /**
* Registers a lifetime extender. Lifetime extenders can cause notifications that have been
* dismissed or retracted by system server to be temporarily retained in the collection.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManager.kt
index fad0e49..2b620a4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManager.kt
@@ -23,9 +23,11 @@
import android.service.notification.NotificationListenerService.RankingMap
import android.service.notification.StatusBarNotification
import com.android.systemui.statusbar.NotificationMediaManager
+import com.android.systemui.statusbar.notification.NotificationEntryManager.KeyguardEnvironment
import com.android.systemui.statusbar.notification.NotificationEntryManagerLogger
import com.android.systemui.statusbar.notification.NotificationFilter
import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager
+import com.android.systemui.statusbar.notification.collection.legacy.LegacyNotificationRanker
import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier
@@ -39,7 +41,6 @@
import dagger.Lazy
import java.util.Objects
import javax.inject.Inject
-import kotlin.Comparator
private const val TAG = "NotifRankingManager"
@@ -60,10 +61,11 @@
private val logger: NotificationEntryManagerLogger,
private val sectionsFeatureManager: NotificationSectionsFeatureManager,
private val peopleNotificationIdentifier: PeopleNotificationIdentifier,
- private val highPriorityProvider: HighPriorityProvider
-) {
+ private val highPriorityProvider: HighPriorityProvider,
+ private val keyguardEnvironment: KeyguardEnvironment
+) : LegacyNotificationRanker {
- var rankingMap: RankingMap? = null
+ override var rankingMap: RankingMap? = null
protected set
private val mediaManager by lazy {
mediaManagerLazy.get()
@@ -115,7 +117,7 @@
}
}
- fun updateRanking(
+ override fun updateRanking(
newRankingMap: RankingMap?,
entries: Collection<NotificationEntry>,
reason: String
@@ -131,6 +133,12 @@
}
}
+ override fun isNotificationForCurrentProfiles(
+ entry: NotificationEntry
+ ): Boolean {
+ return keyguardEnvironment.isNotificationForCurrentProfiles(entry.sbn)
+ }
+
/** Uses the [rankingComparator] to sort notifications which aren't filtered */
private fun filterAndSortLocked(
entries: Collection<NotificationEntry>,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/Coordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/Coordinator.java
index c1a11b2..2357072 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/Coordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/Coordinator.java
@@ -16,6 +16,8 @@
package com.android.systemui.statusbar.notification.collection.coordinator;
+import androidx.annotation.NonNull;
+
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Pluggable;
@@ -27,5 +29,5 @@
* Called after the NewNotifPipeline is initialized.
* Coordinators should register their listeners and {@link Pluggable}s to the pipeline.
*/
- void attach(NotifPipeline pipeline);
+ void attach(@NonNull NotifPipeline pipeline);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.java
index ded5e46..d80cc08 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.java
@@ -60,6 +60,7 @@
ConversationCoordinator conversationCoordinator,
PreparationCoordinator preparationCoordinator,
MediaCoordinator mediaCoordinator,
+ SmartspaceDedupingCoordinator smartspaceDedupingCoordinator,
VisualStabilityCoordinator visualStabilityCoordinator) {
dumpManager.registerDumpable(TAG, this);
@@ -70,9 +71,14 @@
mCoordinators.add(appOpsCoordinator);
mCoordinators.add(deviceProvisionedCoordinator);
mCoordinators.add(bubbleCoordinator);
- mCoordinators.add(mediaCoordinator);
mCoordinators.add(conversationCoordinator);
+ mCoordinators.add(mediaCoordinator);
mCoordinators.add(visualStabilityCoordinator);
+
+ if (featureFlags.isSmartspaceDedupingEnabled()) {
+ mCoordinators.add(smartspaceDedupingCoordinator);
+ }
+
if (featureFlags.isNewNotifPipelineRenderingEnabled()) {
mCoordinators.add(headsUpCoordinator);
mCoordinators.add(preparationCoordinator);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SmartspaceDedupingCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SmartspaceDedupingCoordinator.kt
new file mode 100644
index 0000000..442d9d2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SmartspaceDedupingCoordinator.kt
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.collection.coordinator
+
+import android.app.smartspace.SmartspaceTarget
+import android.os.Parcelable
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.plugins.statusbar.StatusBarStateController
+import com.android.systemui.statusbar.NotificationLockscreenUserManager
+import com.android.systemui.statusbar.StatusBarState
+import com.android.systemui.statusbar.SysuiStatusBarStateController
+import com.android.systemui.statusbar.lockscreen.LockscreenSmartspaceController
+import com.android.systemui.statusbar.notification.NotificationEntryManager
+import com.android.systemui.statusbar.notification.collection.NotifPipeline
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener
+import com.android.systemui.util.concurrency.DelayableExecutor
+import com.android.systemui.util.time.SystemClock
+import java.util.concurrent.TimeUnit.SECONDS
+import javax.inject.Inject
+
+/**
+ * Hides notifications on the lockscreen if the content of those notifications is also visible
+ * in smartspace. This ONLY hides the notifications on the lockscreen: if the user pulls the shade
+ * down or unlocks the device, then the notifications are unhidden.
+ *
+ * In addition, notifications that have recently alerted aren't filtered. Tracking this in a way
+ * that involves the fewest pipeline invalidations requires some unfortunately complex logic.
+ */
+// This class is a singleton so that the same instance can be accessed by both the old and new
+// pipelines
+@SysUISingleton
+class SmartspaceDedupingCoordinator @Inject constructor(
+ private val statusBarStateController: SysuiStatusBarStateController,
+ private val smartspaceController: LockscreenSmartspaceController,
+ private val notificationEntryManager: NotificationEntryManager,
+ private val notificationLockscreenUserManager: NotificationLockscreenUserManager,
+ private val notifPipeline: NotifPipeline,
+ @Main private val executor: DelayableExecutor,
+ private val clock: SystemClock
+) : Coordinator {
+ private var isOnLockscreen = false
+
+ private var trackedSmartspaceTargets = mutableMapOf<String, TrackedSmartspaceTarget>()
+
+ override fun attach(pipeline: NotifPipeline) {
+ pipeline.addPreGroupFilter(filter)
+ pipeline.addCollectionListener(collectionListener)
+ statusBarStateController.addCallback(statusBarStateListener)
+ smartspaceController.addListener(this::onNewSmartspaceTargets)
+
+ // TODO (b/173126564): Remove this once the old pipeline is no longer necessary
+ notificationLockscreenUserManager.addKeyguardNotificationSuppressor { entry ->
+ isDupedWithSmartspaceContent(entry)
+ }
+
+ recordStatusBarState(statusBarStateController.state)
+ }
+
+ private fun isDupedWithSmartspaceContent(entry: NotificationEntry): Boolean {
+ return trackedSmartspaceTargets[entry.key]?.shouldFilter ?: false
+ }
+
+ private val filter = object : NotifFilter("SmartspaceDedupingFilter") {
+ override fun shouldFilterOut(entry: NotificationEntry, now: Long): Boolean {
+ return isOnLockscreen && isDupedWithSmartspaceContent(entry)
+ }
+ }
+
+ private val collectionListener = object : NotifCollectionListener {
+ override fun onEntryAdded(entry: NotificationEntry) {
+ trackedSmartspaceTargets[entry.key]?.let {
+ updateFilterStatus(it)
+ }
+ }
+
+ override fun onEntryUpdated(entry: NotificationEntry) {
+ trackedSmartspaceTargets[entry.key]?.let {
+ updateFilterStatus(it)
+ }
+ }
+
+ override fun onEntryRemoved(entry: NotificationEntry, reason: Int) {
+ trackedSmartspaceTargets[entry.key]?.let { trackedTarget ->
+ cancelExceptionTimeout(trackedTarget)
+ }
+ }
+ }
+
+ private val statusBarStateListener = object : StatusBarStateController.StateListener {
+ override fun onStateChanged(newState: Int) {
+ recordStatusBarState(newState)
+ }
+ }
+
+ private fun onNewSmartspaceTargets(targets: List<Parcelable>) {
+ var changed = false
+ val newMap = mutableMapOf<String, TrackedSmartspaceTarget>()
+ val oldMap = trackedSmartspaceTargets
+
+ for (target in targets) {
+ // For all targets that are SmartspaceTargets and have non-null sourceNotificationKeys
+ (target as? SmartspaceTarget)?.sourceNotificationKey?.let { key ->
+ val trackedTarget = oldMap.getOrElse(key) {
+ TrackedSmartspaceTarget(key)
+ }
+ newMap[key] = trackedTarget
+ changed = changed || updateFilterStatus(trackedTarget)
+ }
+ // Currently, only filter out the first target
+ break
+ }
+
+ for (prevKey in oldMap.keys) {
+ if (!newMap.containsKey(prevKey)) {
+ oldMap[prevKey]?.cancelTimeoutRunnable?.run()
+ changed = true
+ }
+ }
+
+ if (changed) {
+ filter.invalidateList()
+ notificationEntryManager.updateNotifications("Smartspace targets changed")
+ }
+
+ trackedSmartspaceTargets = newMap
+ }
+
+ /**
+ * Returns true if the target's alert exception status has changed
+ */
+ private fun updateFilterStatus(target: TrackedSmartspaceTarget): Boolean {
+ val prevShouldFilter = target.shouldFilter
+
+ val entry = notifPipeline.getEntry(target.key)
+ if (entry != null) {
+ updateAlertException(target, entry)
+
+ target.shouldFilter = !hasRecentlyAlerted(entry)
+ }
+
+ return target.shouldFilter != prevShouldFilter && isOnLockscreen
+ }
+
+ private fun updateAlertException(target: TrackedSmartspaceTarget, entry: NotificationEntry) {
+ val now = clock.currentTimeMillis()
+ val alertExceptionExpires = entry.ranking.lastAudiblyAlertedMillis + ALERT_WINDOW
+
+ if (alertExceptionExpires != target.alertExceptionExpires &&
+ alertExceptionExpires > now) {
+ // If we got here, the target is subject to a new alert exception window, so we
+ // should update our timeout to fire at the end of the new window
+
+ target.cancelTimeoutRunnable?.run()
+ target.alertExceptionExpires = alertExceptionExpires
+ target.cancelTimeoutRunnable = executor.executeDelayed({
+ target.cancelTimeoutRunnable = null
+ target.shouldFilter = true
+ filter.invalidateList()
+ notificationEntryManager.updateNotifications("deduping timeout expired")
+ }, alertExceptionExpires - now)
+ }
+ }
+
+ private fun cancelExceptionTimeout(target: TrackedSmartspaceTarget) {
+ target.cancelTimeoutRunnable?.run()
+ target.cancelTimeoutRunnable = null
+ target.alertExceptionExpires = 0
+ }
+
+ private fun recordStatusBarState(newState: Int) {
+ val wasOnLockscreen = isOnLockscreen
+ isOnLockscreen = newState == StatusBarState.KEYGUARD
+
+ if (isOnLockscreen != wasOnLockscreen) {
+ filter.invalidateList()
+ // No need to call notificationEntryManager.updateNotifications; something else already
+ // does it for us when the keyguard state changes
+ }
+ }
+
+ private fun hasRecentlyAlerted(entry: NotificationEntry): Boolean {
+ return clock.currentTimeMillis() - entry.ranking.lastAudiblyAlertedMillis <= ALERT_WINDOW
+ }
+}
+
+private class TrackedSmartspaceTarget(
+ val key: String
+) {
+ var cancelTimeoutRunnable: Runnable? = null
+ var alertExceptionExpires: Long = 0
+ var shouldFilter = false
+}
+
+private val ALERT_WINDOW = SECONDS.toMillis(30)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/LegacyNotificationRanker.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/LegacyNotificationRanker.kt
new file mode 100644
index 0000000..49bc48e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/LegacyNotificationRanker.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.collection.legacy
+
+import android.service.notification.NotificationListenerService
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+
+interface LegacyNotificationRanker {
+ val rankingMap: NotificationListenerService.RankingMap?
+
+ fun updateRanking(
+ newRankingMap: NotificationListenerService.RankingMap?,
+ entries: Collection<NotificationEntry>,
+ reason: String
+ ): List<NotificationEntry>
+
+ fun isNotificationForCurrentProfiles(
+ entry: NotificationEntry
+ ): Boolean
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/LegacyNotificationRankerStub.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/LegacyNotificationRankerStub.java
new file mode 100644
index 0000000..12353f8
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/LegacyNotificationRankerStub.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.collection.legacy;
+
+import android.service.notification.NotificationListenerService.Ranking;
+import android.service.notification.NotificationListenerService.RankingMap;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.List;
+
+/**
+ * Stub implementation that we use until we get passed the "real" one in the form of
+ * {@link com.android.systemui.statusbar.notification.collection.NotificationRankingManager}
+ */
+public class LegacyNotificationRankerStub implements LegacyNotificationRanker {
+ private RankingMap mRankingMap = new RankingMap(new Ranking[] {});
+
+ @NonNull
+ @Override
+ public List<NotificationEntry> updateRanking(
+ @Nullable RankingMap newRankingMap,
+ @NonNull Collection<NotificationEntry> entries,
+ @NonNull String reason) {
+ if (newRankingMap != null) {
+ mRankingMap = newRankingMap;
+ }
+ List<NotificationEntry> ranked = new ArrayList<>(entries);
+ ranked.sort(mEntryComparator);
+ return ranked;
+ }
+
+ @Nullable
+ @Override
+ public RankingMap getRankingMap() {
+ return mRankingMap;
+ }
+
+ private final Comparator<NotificationEntry> mEntryComparator = Comparator.comparingLong(
+ o -> o.getSbn().getNotification().when);
+
+ @Override
+ public boolean isNotificationForCurrentProfiles(@NonNull NotificationEntry entry) {
+ return true;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifFilter.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifFilter.java
index 9edb5fc..776c7d5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifFilter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifFilter.java
@@ -16,6 +16,8 @@
package com.android.systemui.statusbar.notification.collection.listbuilder.pluggable;
+import androidx.annotation.NonNull;
+
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -45,5 +47,5 @@
* various entries against.
* @return True if the notif should be removed from the list
*/
- public abstract boolean shouldFilterOut(NotificationEntry entry, long now);
+ public abstract boolean shouldFilterOut(@NonNull NotificationEntry entry, long now);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
index 89bb652..a32b7e3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
@@ -44,7 +44,6 @@
import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifInflaterImpl;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
-import com.android.systemui.statusbar.notification.collection.NotificationRankingManager;
import com.android.systemui.statusbar.notification.collection.coordinator.VisualStabilityCoordinator;
import com.android.systemui.statusbar.notification.collection.inflation.NotifInflater;
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder;
@@ -100,8 +99,6 @@
static NotificationEntryManager provideNotificationEntryManager(
NotificationEntryManagerLogger logger,
NotificationGroupManagerLegacy groupManager,
- Lazy<NotificationRankingManager> rankingManager,
- NotificationEntryManager.KeyguardEnvironment keyguardEnvironment,
FeatureFlags featureFlags,
Lazy<NotificationRowBinder> notificationRowBinderLazy,
Lazy<NotificationRemoteInputManager> notificationRemoteInputManagerLazy,
@@ -111,8 +108,6 @@
return new NotificationEntryManager(
logger,
groupManager,
- rankingManager,
- keyguardEnvironment,
featureFlags,
notificationRowBinderLazy,
notificationRemoteInputManagerLazy,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt
index fd5128a..88ca86b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt
@@ -16,7 +16,6 @@
package com.android.systemui.statusbar.notification.init
-import android.content.Context
import android.service.notification.StatusBarNotification
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.people.widget.PeopleSpaceWidgetManager
@@ -30,6 +29,7 @@
import com.android.systemui.statusbar.notification.NotificationEntryManager
import com.android.systemui.statusbar.notification.NotificationListController
import com.android.systemui.statusbar.notification.collection.NotifPipeline
+import com.android.systemui.statusbar.notification.collection.NotificationRankingManager
import com.android.systemui.statusbar.notification.collection.TargetSdkResolver
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl
import com.android.systemui.statusbar.notification.collection.init.NotifPipelineInitializer
@@ -59,10 +59,10 @@
*/
@SysUISingleton
class NotificationsControllerImpl @Inject constructor(
- private val context: Context,
private val featureFlags: FeatureFlags,
private val notificationListener: NotificationListener,
private val entryManager: NotificationEntryManager,
+ private val legacyRanker: NotificationRankingManager,
private val notifPipeline: Lazy<NotifPipeline>,
private val targetSdkResolver: TargetSdkResolver,
private val newNotifPipeline: Lazy<NotifPipelineInitializer>,
@@ -128,6 +128,7 @@
groupManagerLegacy.get().setHeadsUpManager(headsUpManager)
groupAlertTransferHelper.setHeadsUpManager(headsUpManager)
+ entryManager.setRanker(legacyRanker)
entryManager.attach(notificationListener)
}
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 caf4720..66d2347 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
@@ -95,6 +95,7 @@
/** Height of the notifications panel without top padding when expansion completes. */
private float mStackEndHeight;
+ private float mTransitionToFullShadeAmount;
/**
* @return Height of the notifications panel without top padding when expansion completes.
@@ -595,6 +596,21 @@
}
/**
+ * Set the amount of pixels we have currently dragged down if we're transitioning to the full
+ * shade. 0.0f means we're not transitioning yet.
+ */
+ public void setTransitionToFullShadeAmount(float transitionToFullShadeAmount) {
+ mTransitionToFullShadeAmount = transitionToFullShadeAmount;
+ }
+
+ /**
+ * get
+ */
+ public float getTransitionToFullShadeAmount() {
+ return mTransitionToFullShadeAmount;
+ }
+
+ /**
* Returns the currently tracked heads up row, if there is one and it is currently above the
* shelf (still appearing).
*/
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 786fe2c..a804ae6 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
@@ -46,7 +46,6 @@
import android.os.UserHandle;
import android.provider.Settings;
import android.util.AttributeSet;
-import android.util.DisplayMetrics;
import android.util.Log;
import android.util.MathUtils;
import android.util.Pair;
@@ -71,17 +70,14 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.graphics.ColorUtils;
import com.android.internal.jank.InteractionJankMonitor;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.keyguard.KeyguardSliceView;
import com.android.settingslib.Utils;
-import com.android.systemui.Dependency;
import com.android.systemui.Dumpable;
import com.android.systemui.ExpandHelper;
import com.android.systemui.R;
import com.android.systemui.animation.Interpolators;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.DragDownHelper.DragDownCallback;
import com.android.systemui.statusbar.EmptyShadeView;
import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
@@ -89,7 +85,6 @@
import com.android.systemui.statusbar.NotificationShelfController;
import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.ExpandAnimationParameters;
import com.android.systemui.statusbar.notification.FakeShadowView;
import com.android.systemui.statusbar.notification.NotificationActivityStarter;
@@ -108,9 +103,6 @@
import com.android.systemui.statusbar.notification.row.StackScrollerDecorView;
import com.android.systemui.statusbar.phone.HeadsUpAppearanceController;
import com.android.systemui.statusbar.phone.HeadsUpTouchHelper;
-import com.android.systemui.statusbar.phone.LockscreenGestureLogger;
-import com.android.systemui.statusbar.phone.LockscreenGestureLogger.LockscreenUiEvent;
-import com.android.systemui.statusbar.phone.NotificationPanelViewController;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.policy.HeadsUpUtil;
@@ -151,7 +143,6 @@
*/
private static final int DISTANCE_BETWEEN_ADJACENT_SECTIONS_PX = 1;
private KeyguardBypassEnabledProvider mKeyguardBypassEnabledProvider;
- private final SysuiStatusBarStateController mStatusbarStateController;
private ExpandHelper mExpandHelper;
private NotificationSwipeHelper mSwipeHelper;
@@ -433,13 +424,9 @@
private ShadeController mShadeController;
private Runnable mOnStackYChanged;
- private final DisplayMetrics mDisplayMetrics = Dependency.get(DisplayMetrics.class);
- private final LockscreenGestureLogger mLockscreenGestureLogger =
- Dependency.get(LockscreenGestureLogger.class);
protected boolean mClearAllEnabled;
private Interpolator mHideXInterpolator = Interpolators.FAST_OUT_SLOW_IN;
- private NotificationPanelViewController mNotificationPanelController;
private final NotificationSectionsManager mSectionsManager;
private ForegroundServiceDungeonView mFgsSectionView;
@@ -449,6 +436,11 @@
private boolean mWillExpand;
private int mGapHeight;
+ /**
+ * The extra inset during the full shade transition
+ */
+ private float mExtraTopInsetForFullShadeTransition;
+
private int mWaterfallTopInset;
private NotificationStackScrollLayoutController mController;
@@ -496,7 +488,6 @@
NotificationSectionsManager notificationSectionsManager,
GroupMembershipManager groupMembershipManager,
GroupExpansionManager groupExpansionManager,
- SysuiStatusBarStateController statusbarStateController,
AmbientState ambientState,
FeatureFlags featureFlags) {
super(context, attrs, 0, 0);
@@ -535,7 +526,6 @@
mClearAllEnabled = res.getBoolean(R.bool.config_enableNotificationsClearAll);
mGroupMembershipManager = groupMembershipManager;
mGroupExpansionManager = groupExpansionManager;
- mStatusbarStateController = statusbarStateController;
}
void initializeForegroundServiceSection(ForegroundServiceDungeonView fgsSectionView) {
@@ -664,7 +654,7 @@
mDebugPaint.setColor(Color.CYAN);
canvas.drawLine(0, y, getWidth(), y, mDebugPaint);
- y = (int) (mAmbientState.getStackY() + mSidePaddings + mAmbientState.getStackHeight());
+ y = (int) (mAmbientState.getStackY() + mAmbientState.getStackHeight());
mDebugPaint.setColor(Color.BLUE);
canvas.drawLine(0, y, getWidth(), y, mDebugPaint);
}
@@ -1142,8 +1132,9 @@
*/
private void updateStackPosition() {
// Consider interpolating from an mExpansionStartY for use on lockscreen and AOD
+ float endTopPosition = mTopPadding + mExtraTopInsetForFullShadeTransition;
final float fraction = mAmbientState.getExpansionFraction();
- final float stackY = MathUtils.lerp(0, mTopPadding, fraction);
+ final float stackY = MathUtils.lerp(0, endTopPosition, fraction);
mAmbientState.setStackY(stackY);
if (mOnStackYChanged != null) {
mOnStackYChanged.run();
@@ -1151,7 +1142,7 @@
if (mQsExpansionFraction <= 0) {
final float scrimTopPadding = mAmbientState.isOnKeyguard() ? 0 : mSidePaddings;
final float stackEndHeight = Math.max(0f,
- getHeight() - getEmptyBottomMargin() - stackY - scrimTopPadding);
+ getHeight() - getEmptyBottomMargin() - mTopPadding);
mAmbientState.setStackEndHeight(stackEndHeight);
mAmbientState.setStackHeight(
MathUtils.lerp(stackEndHeight * StackScrollAlgorithm.START_FRACTION,
@@ -2068,18 +2059,22 @@
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
private void updateContentHeight() {
- int height = 0;
+ final float scrimTopPadding = mAmbientState.isOnKeyguard() ? 0 : mSidePaddings;
+ int height = (int) scrimTopPadding;
float previousPaddingRequest = mPaddingBetweenElements;
int numShownItems = 0;
int numShownNotifs = 0;
boolean finish = false;
int maxDisplayedNotifications = mMaxDisplayedNotifications;
ExpandableView previousView = null;
+
for (int i = 0; i < getChildCount(); i++) {
ExpandableView expandableView = (ExpandableView) getChildAt(i);
boolean footerViewOnLockScreen = expandableView == mFooterView && onKeyguard();
+
if (expandableView.getVisibility() != View.GONE
&& !expandableView.hasNoContentHeight() && !footerViewOnLockScreen) {
+
boolean limitReached = maxDisplayedNotifications != -1
&& numShownNotifs >= maxDisplayedNotifications;
final float viewHeight;
@@ -4274,6 +4269,13 @@
+ mGapHeight;
}
+ /**
+ * @return the padding after the media header on the lockscreen
+ */
+ public int getPaddingAfterMedia() {
+ return mGapHeight + mPaddingBetweenElements;
+ }
+
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
public int getEmptyShadeViewHeight() {
return mEmptyShadeView.getHeight();
@@ -4929,12 +4931,6 @@
getChildCount() - offsetFromEnd);
}
- @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
- public void setNotificationPanelController(
- NotificationPanelViewController notificationPanelViewController) {
- mNotificationPanelController = notificationPanelViewController;
- }
-
/**
* Set how far the wake up is when waking up from pulsing. This is a height and will adjust the
* notification positions accordingly.
@@ -5151,6 +5147,16 @@
}
/**
+ * Sets the extra top inset for the full shade transition. This is needed to compensate for
+ * media transitioning to quick settings
+ */
+ public void setExtraTopInsetForFullShadeTransition(float inset) {
+ mExtraTopInsetForFullShadeTransition = inset;
+ updateStackPosition();
+ requestChildrenUpdate();
+ }
+
+ /**
* A listener that is notified when the empty space below the notifications is clicked on
*/
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
@@ -5522,108 +5528,10 @@
}
}
- public void setKeyguardMediaControllorVisible(boolean keyguardMediaControllorVisible) {
- mKeyguardMediaControllorVisible = keyguardMediaControllorVisible;
- }
-
void resetCheckSnoozeLeavebehind() {
setCheckForLeaveBehind(true);
}
- // ---------------------- DragDownHelper.OnDragDownListener ------------------------------------
-
- @ShadeViewRefactor(RefactorComponent.INPUT)
- private final DragDownCallback mDragDownCallback = new DragDownCallback() {
-
- @Override
- public boolean canDragDown() {
- return mStatusBarState == StatusBarState.KEYGUARD
- && (mController.hasActiveNotifications() || mKeyguardMediaControllorVisible)
- || mController.isInLockedDownShade();
- }
-
- /* Only ever called as a consequence of a lockscreen expansion gesture. */
- @Override
- public void onDraggedDown(View startingChild, int dragLengthY) {
- boolean canDragDown =
- mController.hasActiveNotifications() || mKeyguardMediaControllorVisible;
- if (mStatusBarState == StatusBarState.KEYGUARD && canDragDown) {
- mLockscreenGestureLogger.write(
- MetricsEvent.ACTION_LS_SHADE,
- (int) (dragLengthY / mDisplayMetrics.density),
- 0 /* velocityDp - N/A */);
- mLockscreenGestureLogger.log(LockscreenUiEvent.LOCKSCREEN_PULL_SHADE_OPEN);
-
- if (!mAmbientState.isDozing() || startingChild != null) {
- // We have notifications, go to locked shade.
- mShadeController.goToLockedShade(startingChild);
- if (startingChild instanceof ExpandableNotificationRow) {
- ExpandableNotificationRow row = (ExpandableNotificationRow) startingChild;
- row.onExpandedByGesture(true /* drag down is always an open */);
- }
- }
- } else if (mController.isInLockedDownShade()) {
- mStatusbarStateController.setLeaveOpenOnKeyguardHide(true);
- mStatusBar.dismissKeyguardThenExecute(() -> false /* dismissAction */,
- null /* cancelRunnable */, false /* afterKeyguardGone */);
- }
- }
-
- @Override
- public void onDragDownReset() {
- setDimmed(true /* dimmed */, true /* animated */);
- resetScrollPosition();
- resetCheckSnoozeLeavebehind();
- }
-
- @Override
- public void onCrossedThreshold(boolean above) {
- setDimmed(!above /* dimmed */, true /* animate */);
- }
-
- @Override
- public void onTouchSlopExceeded() {
- cancelLongPress();
- mController.checkSnoozeLeavebehind();
- }
-
- @Override
- public void setEmptyDragAmount(float amount) {
- mNotificationPanelController.setEmptyDragAmount(amount);
- }
-
- @Override
- public boolean isFalsingCheckNeeded() {
- return mStatusBarState == StatusBarState.KEYGUARD;
- }
-
- @Override
- public boolean isDragDownEnabledForView(ExpandableView view) {
- if (isDragDownAnywhereEnabled()) {
- return true;
- }
- if (mController.isInLockedDownShade()) {
- if (view == null) {
- // Dragging down is allowed in general
- return true;
- }
- if (view instanceof ExpandableNotificationRow) {
- // Only drag down on sensitive views, otherwise the ExpandHelper will take this
- return ((ExpandableNotificationRow) view).getEntry().isSensitive();
- }
- }
- return false;
- }
-
- @Override
- public boolean isDragDownAnywhereEnabled() {
- return mStatusbarStateController.getState() == StatusBarState.KEYGUARD
- && !mKeyguardBypassEnabledProvider.getBypassEnabled();
- }
- };
-
- public DragDownCallback getDragDownCallback() { return mDragDownCallback; }
-
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
private final HeadsUpTouchHelper.Callback mHeadsUpCallback = new HeadsUpTouchHelper.Callback() {
@Override
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 f7eb574..0d42428 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
@@ -31,6 +31,7 @@
import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.canChildBeDismissed;
import static com.android.systemui.statusbar.phone.NotificationIconAreaController.HIGH_PRIORITY;
+import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Point;
import android.graphics.PointF;
@@ -38,6 +39,7 @@
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.util.Log;
+import android.util.MathUtils;
import android.util.Pair;
import android.view.Display;
import android.view.LayoutInflater;
@@ -59,6 +61,7 @@
import com.android.systemui.Gefingerpoken;
import com.android.systemui.R;
import com.android.systemui.SwipeHelper;
+import com.android.systemui.animation.Interpolators;
import com.android.systemui.classifier.Classifier;
import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.colorextraction.SysuiColorExtractor;
@@ -70,6 +73,7 @@
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.FeatureFlags;
+import com.android.systemui.statusbar.LockscreenShadeTransitionController;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationLockscreenUserManager.UserChangedListener;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
@@ -107,7 +111,6 @@
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
import com.android.systemui.statusbar.phone.HeadsUpTouchHelper;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
-import com.android.systemui.statusbar.phone.NotificationPanelViewController;
import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -168,6 +171,7 @@
// TODO: StatusBar should be encapsulated behind a Controller
private final StatusBar mStatusBar;
private final SectionHeaderController mSilentHeaderController;
+ private final LockscreenShadeTransitionController mLockscreenShadeTransitionController;
private NotificationStackScrollLayout mView;
private boolean mFadeNotificationsOnDismiss;
@@ -181,6 +185,9 @@
private ColorExtractor.OnColorsChangedListener mOnColorsChangedListener;
+ private int mTotalDistanceForFullShadeTransition;
+ private int mTotalExtraMediaInsetFullShadeTransition;
+
@VisibleForTesting
final View.OnAttachStateChangeListener mOnAttachStateChangeListener =
new View.OnAttachStateChangeListener() {
@@ -240,8 +247,20 @@
public void onThemeChanged() {
updateFooter();
}
+
+ @Override
+ public void onConfigChanged(Configuration newConfig) {
+ updateResources();
+ }
};
+ private void updateResources() {
+ mTotalExtraMediaInsetFullShadeTransition = mResources.getDimensionPixelSize(
+ R.dimen.lockscreen_shade_transition_extra_media_inset);
+ mTotalDistanceForFullShadeTransition = mResources.getDimensionPixelSize(
+ R.dimen.lockscreen_shade_qs_transition_distance);
+ }
+
private final StatusBarStateController.StateListener mStateListener =
new StatusBarStateController.StateListener() {
@Override
@@ -571,6 +590,7 @@
NotifPipeline notifPipeline,
NotifCollection notifCollection,
NotificationEntryManager notificationEntryManager,
+ LockscreenShadeTransitionController lockscreenShadeTransitionController,
IStatusBarService iStatusBarService,
UiEventLogger uiEventLogger,
ForegroundServiceDismissalFeatureController fgFeatureController,
@@ -592,6 +612,7 @@
mZenModeController = zenModeController;
mLockscreenUserManager = lockscreenUserManager;
mMetricsLogger = metricsLogger;
+ mLockscreenShadeTransitionController = lockscreenShadeTransitionController;
mFalsingCollector = falsingCollector;
mFalsingManager = falsingManager;
mResources = resources;
@@ -624,6 +645,7 @@
mRemoteInputManager = remoteInputManager;
mVisualStabilityManager = visualStabilityManager;
mShadeController = shadeController;
+ updateResources();
}
public void attach(NotificationStackScrollLayout view) {
@@ -676,6 +698,8 @@
mScrimController.setScrimBehindChangeRunnable(mView::updateBackgroundDimming);
+ mLockscreenShadeTransitionController.setStackScroller(this);
+
mLockscreenUserManager.addUserChangedListener(mLockscreenUserChangeListener);
mFadeNotificationsOnDismiss = // TODO: this should probably be injected directly
@@ -705,7 +729,6 @@
Settings.Secure.NOTIFICATION_HISTORY_ENABLED);
mKeyguardMediaController.setVisibilityChangedListener(visible -> {
- mView.setKeyguardMediaControllorVisible(visible);
if (visible) {
mView.generateAddAnimation(
mKeyguardMediaController.getSinglePaneContainer(),
@@ -1203,11 +1226,6 @@
mView.runAfterAnimationFinished(r);
}
- public void setNotificationPanelController(
- NotificationPanelViewController notificationPanelViewController) {
- mView.setNotificationPanelController(notificationPanelViewController);
- }
-
public void setShelfController(NotificationShelfController notificationShelfController) {
mView.setShelfController(notificationShelfController);
}
@@ -1275,7 +1293,10 @@
NotificationLogger.getNotificationLocation(entry)));
}
- boolean hasActiveNotifications() {
+ /**
+ * @return if the shade has currently any active notifications.
+ */
+ public boolean hasActiveNotifications() {
if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
return !mNotifPipeline.getShadeList().isEmpty();
} else {
@@ -1354,11 +1375,60 @@
}
}
+ /**
+ * @return the expand helper callback.
+ */
+ public ExpandHelper.Callback getExpandHelperCallback() {
+ return mView.getExpandHelperCallback();
+ }
+
+ /**
+ * @return If the shade is in the locked down shade.
+ */
public boolean isInLockedDownShade() {
return mDynamicPrivacyController.isInLockedDownShade();
}
/**
+ * Set the dimmed state for all of the notification views.
+ */
+ public void setDimmed(boolean dimmed, boolean animate) {
+ mView.setDimmed(dimmed, animate);
+ }
+
+ /**
+ * @return the inset during the full shade transition, that needs to be added to the position
+ * of the quick settings edge. This is relevant for media, that is transitioning
+ * from the keyguard host to the quick settings one.
+ */
+ public int getFullShadeTransitionInset() {
+ MediaHeaderView view = mKeyguardMediaController.getSinglePaneContainer();
+ if (view == null || view.getHeight() == 0
+ || mStatusBarStateController.getState() != KEYGUARD) {
+ return 0;
+ }
+ return view.getHeight() + mView.getPaddingAfterMedia();
+ }
+
+ /**
+ * Set the amount of pixels we have currently dragged down if we're transitioning to the full
+ * shade. 0.0f means we're not transitioning yet.
+ */
+ public void setTransitionToFullShadeAmount(float amount) {
+ float extraTopInset;
+ MediaHeaderView view = mKeyguardMediaController.getSinglePaneContainer();
+ if (view == null || view.getHeight() == 0
+ || mStatusBarStateController.getState() != KEYGUARD) {
+ extraTopInset = 0;
+ } else {
+ extraTopInset = MathUtils.saturate(amount / mTotalDistanceForFullShadeTransition);
+ extraTopInset = Interpolators.FAST_OUT_SLOW_IN.getInterpolation(extraTopInset);
+ extraTopInset = extraTopInset * mTotalExtraMediaInsetFullShadeTransition;
+ }
+ mView.setExtraTopInsetForFullShadeTransition(extraTopInset);
+ }
+
+ /**
* Enum for UiEvent logged from this class
*/
enum NotificationPanelEvent implements UiEventLogger.UiEventEnum {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
index b2d39a9..e931ec4 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
@@ -225,6 +225,8 @@
// already accounted for by the top padding and doesn't need an additional adaption
scrollY = Math.max(0, scrollY);
state.scrollY = (int) (scrollY + bottomOverScroll);
+ state.mCurrentYPosition = -state.scrollY;
+ state.mCurrentExpandedYPosition = -state.scrollY;
//now init the visible children and update paddings
int childCount = hostView.getChildCount();
@@ -321,14 +323,14 @@
*/
private void updatePositionsForState(StackScrollAlgorithmState algorithmState,
AmbientState ambientState) {
- // The y coordinate of the current child.
- float currentYPosition = -algorithmState.scrollY;
if (!ambientState.isOnKeyguard()) {
- currentYPosition += mNotificationScrimPadding;
+ algorithmState.mCurrentYPosition += mNotificationScrimPadding;
+ algorithmState.mCurrentExpandedYPosition += mNotificationScrimPadding;
}
+
int childCount = algorithmState.visibleChildren.size();
for (int i = 0; i < childCount; i++) {
- currentYPosition = updateChild(i, algorithmState, ambientState, currentYPosition);
+ updateChild(i, algorithmState, ambientState);
}
}
@@ -348,14 +350,14 @@
StackScrollAlgorithmState algorithmState,
AmbientState ambientState) {
- final boolean isShowingShelf = ambientState.getShelf() != null
+ final boolean showingShelf = ambientState.getShelf() != null
&& algorithmState.firstViewInShelf != null;
- final float stackHeight = ambientState.getStackHeight()
- - (isShowingShelf ? ambientState.getShelf().getIntrinsicHeight() : 0f);
+ final float shelfHeight = showingShelf ? ambientState.getShelf().getIntrinsicHeight() : 0f;
+ final float scrimPadding = ambientState.isOnKeyguard() ? 0 : mNotificationScrimPadding;
- float stackEndHeight = ambientState.getStackEndHeight()
- - (isShowingShelf ? ambientState.getShelf().getIntrinsicHeight() : 0f);
+ final float stackHeight = ambientState.getStackHeight() - shelfHeight - scrimPadding;
+ final float stackEndHeight = ambientState.getStackEndHeight() - shelfHeight - scrimPadding;
return stackHeight / stackEndHeight;
}
@@ -368,17 +370,11 @@
* {@link StackScrollAlgorithmState#visibleChildren}.
* @param algorithmState The overall output state of the algorithm.
* @param ambientState The input state provided to the algorithm.
- * @param currentYPosition The Y position of the current pass of the algorithm. For a forward
- * pass, this should be the top of the child; for a reverse pass, the
- * bottom of the child.
- * @return The Y position after laying out the child. This will be the {@code currentYPosition}
- * for the next call to this method, after adjusting for any gaps between children.
*/
- protected float updateChild(
+ protected void updateChild(
int i,
StackScrollAlgorithmState algorithmState,
- AmbientState ambientState,
- float currentYPosition) {
+ AmbientState ambientState) {
ExpandableView view = algorithmState.visibleChildren.get(i);
ExpandableViewState viewState = view.getViewState();
@@ -407,10 +403,11 @@
ambientState.getSectionProvider(), i,
view, getPreviousView(i, algorithmState));
if (applyGapHeight) {
- currentYPosition += expansionFraction * mGapHeight;
+ algorithmState.mCurrentYPosition += expansionFraction * mGapHeight;
+ algorithmState.mCurrentExpandedYPosition += mGapHeight;
}
- viewState.yTranslation = currentYPosition;
+ viewState.yTranslation = algorithmState.mCurrentYPosition;
if (view instanceof SectionHeaderView) {
// Add padding before sections for overscroll effect.
viewState.yTranslation += expansionFraction * ambientState.getSectionPadding();
@@ -419,12 +416,11 @@
if (view instanceof FooterView) {
final boolean isShelfShowing = algorithmState.firstViewInShelf != null;
- final float footerEnd = viewState.yTranslation + view.getIntrinsicHeight();
- final boolean noSpaceForFooter = footerEnd > ambientState.getStackHeight();
+ final float footerEnd = algorithmState.mCurrentExpandedYPosition
+ + view.getIntrinsicHeight();
+ final boolean noSpaceForFooter = footerEnd > ambientState.getStackEndHeight();
- viewState.hidden = isShelfShowing
- || (!ambientState.isExpansionChanging() && noSpaceForFooter);
-
+ viewState.hidden = isShelfShowing || noSpaceForFooter;
} else if (view != ambientState.getTrackedHeadsUpRow()) {
if (ambientState.isExpansionChanging()) {
// Show all views. Views below the shelf will later be clipped (essentially hidden)
@@ -459,14 +455,16 @@
maxViewHeight = algorithmState.viewHeightBeforeShelf;
}
}
- viewState.height = (int) MathUtils.lerp(maxViewHeight * START_FRACTION, maxViewHeight,
- expansionFraction);
+ viewState.height = (int) (maxViewHeight * expansionFraction);
}
- currentYPosition += viewState.height + expansionFraction * mPaddingBetweenElements;
- setLocation(view.getViewState(), currentYPosition, i);
+ algorithmState.mCurrentYPosition += viewState.height
+ + expansionFraction * mPaddingBetweenElements;
+ algorithmState.mCurrentExpandedYPosition += view.getIntrinsicHeight()
+ + mPaddingBetweenElements;
+
+ setLocation(view.getViewState(), algorithmState.mCurrentYPosition, i);
viewState.yTranslation += ambientState.getStackY();
- return currentYPosition;
}
/**
@@ -739,6 +737,18 @@
* The children from the host view which are not gone.
*/
public final ArrayList<ExpandableView> visibleChildren = new ArrayList<>();
+
+ /**
+ * Y position of the current view during updating children
+ * with expansion factor applied.
+ */
+ private int mCurrentYPosition;
+
+ /**
+ * Y position of the current view during updating children
+ * without applying the expansion factor.
+ */
+ private int mCurrentExpandedYPosition;
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
index 16863f6..20e6f60 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
@@ -114,7 +114,8 @@
public static final int MODE_ONLY_WAKE = 4;
/**
- * Mode in which fingerprint unlocks the device.
+ * Mode in which fingerprint unlocks the device or passive auth (ie face auth) unlocks the
+ * device while being requested when keyguard is occluded.
*/
public static final int MODE_UNLOCK_COLLAPSING = 5;
@@ -355,8 +356,10 @@
Optional.ofNullable(BiometricUiEvent.SUCCESS_EVENT_BY_SOURCE_TYPE.get(biometricSourceType))
.ifPresent(UI_EVENT_LOGGER::log);
- boolean unlockAllowed = mKeyguardBypassController.onBiometricAuthenticated(
- biometricSourceType, isStrongBiometric);
+ boolean unlockAllowed =
+ mKeyguardStateController.isOccluded()
+ || mKeyguardBypassController.onBiometricAuthenticated(
+ biometricSourceType, isStrongBiometric);
if (unlockAllowed) {
mKeyguardViewMediator.userActivity();
startWakeAndUnlock(biometricSourceType, isStrongBiometric);
@@ -581,6 +584,9 @@
if (unlockingAllowed && deviceDreaming) {
return bypass ? MODE_WAKE_AND_UNLOCK_FROM_DREAM : MODE_ONLY_WAKE;
}
+ if (unlockingAllowed && mKeyguardStateController.isOccluded()) {
+ return MODE_UNLOCK_COLLAPSING;
+ }
if (mKeyguardViewController.isShowing()) {
if (mKeyguardViewController.bouncerIsOrWillBeShowing() && unlockingAllowed) {
if (bypass && mKeyguardBypassController.canPlaySubtleWindowAnimations()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
index c5a155e..684760e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
@@ -81,7 +81,7 @@
private NetworkController mNetworkController;
private LinearLayout mSystemIconArea;
private View mClockView;
- private ViewGroup mOngoingCallChip;
+ private View mOngoingCallChip;
private View mNotificationIconAreaInner;
private View mCenteredIconArea;
private int mDisabled1;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index c64b893..7f919b5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -39,6 +39,7 @@
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
+import android.database.ContentObserver;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
@@ -48,11 +49,13 @@
import android.os.RemoteException;
import android.os.UserHandle;
import android.provider.MediaStore;
+import android.provider.Settings;
import android.service.media.CameraPrewarmService;
import android.service.quickaccesswallet.GetWalletCardsError;
import android.service.quickaccesswallet.GetWalletCardsRequest;
import android.service.quickaccesswallet.GetWalletCardsResponse;
import android.service.quickaccesswallet.QuickAccessWalletClient;
+import android.service.quickaccesswallet.QuickAccessWalletClientImpl;
import android.telecom.TelecomManager;
import android.text.TextUtils;
import android.util.AttributeSet;
@@ -94,6 +97,7 @@
import com.android.systemui.statusbar.policy.PreviewInflater;
import com.android.systemui.tuner.LockscreenFragment.LockButtonFactory;
import com.android.systemui.tuner.TunerService;
+import com.android.systemui.util.settings.SecureSettings;
import com.android.systemui.wallet.ui.WalletActivity;
import java.util.concurrent.Executor;
@@ -189,6 +193,8 @@
private int mBurnInYOffset;
private ActivityIntentHelper mActivityIntentHelper;
private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+ private ContentObserver mWalletPreferenceObserver;
+ private SecureSettings mSecureSettings;
public KeyguardBottomAreaView(Context context) {
this(context, null);
@@ -251,7 +257,6 @@
super.onFinishInflate();
mPreviewInflater = new PreviewInflater(mContext, new LockPatternUtils(mContext),
new ActivityIntentHelper(mContext));
- mPreviewContainer = findViewById(R.id.preview_container);
mOverlayContainer = findViewById(R.id.overlay_container);
mRightAffordanceView = findViewById(R.id.camera_button);
mLeftAffordanceView = findViewById(R.id.left_button);
@@ -268,7 +273,6 @@
mKeyguardStateController.addCallback(this);
setClipChildren(false);
setClipToPadding(false);
- inflateCameraPreview();
mRightAffordanceView.setOnClickListener(this);
mLeftAffordanceView.setOnClickListener(this);
initAccessibility();
@@ -276,13 +280,21 @@
mFlashlightController = Dependency.get(FlashlightController.class);
mAccessibilityController = Dependency.get(AccessibilityController.class);
mActivityIntentHelper = new ActivityIntentHelper(getContext());
- updateLeftAffordance();
mIndicationPadding = getResources().getDimensionPixelSize(
R.dimen.keyguard_indication_area_padding);
updateWalletVisibility();
}
+ /**
+ * Set the container where the previews are rendered.
+ */
+ public void setPreviewContainer(ViewGroup previewContainer) {
+ mPreviewContainer = previewContainer;
+ inflateCameraPreview();
+ updateLeftAffordance();
+ }
+
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
@@ -319,6 +331,10 @@
mLeftExtension.destroy();
getContext().unregisterReceiver(mDevicePolicyReceiver);
mKeyguardUpdateMonitor.removeCallback(mUpdateMonitorCallback);
+
+ if (mWalletPreferenceObserver != null) {
+ mSecureSettings.unregisterContentObserver(mWalletPreferenceObserver);
+ }
}
private void initAccessibility() {
@@ -560,7 +576,6 @@
}
});
} else {
-
// We need to delay starting the activity because ResolverActivity finishes itself if
// launched behind lockscreen.
mActivityStarter.startActivity(intent, false /* dismissShade */,
@@ -680,6 +695,9 @@
}
private void inflateCameraPreview() {
+ if (mPreviewContainer == null) {
+ return;
+ }
View previewBefore = mCameraPreview;
boolean visibleBefore = false;
if (previewBefore != null) {
@@ -697,6 +715,9 @@
}
private void updateLeftPreview() {
+ if (mPreviewContainer == null) {
+ return;
+ }
View previewBefore = mLeftPreview;
if (previewBefore != null) {
mPreviewContainer.removeView(previewBefore);
@@ -914,15 +935,40 @@
/**
* Initialize the wallet feature, only enabling if the feature is enabled within the platform.
*/
- public void initWallet(QuickAccessWalletClient client, Executor uiExecutor, boolean enabled) {
+ public void initWallet(QuickAccessWalletClient client, Executor uiExecutor,
+ SecureSettings secureSettings) {
mQuickAccessWalletClient = client;
- mWalletEnabled = enabled && client.isWalletFeatureAvailable();
+ mSecureSettings = secureSettings;
+ setupWalletPreferenceObserver();
+ updateWalletPreference();
+
mUiExecutor = uiExecutor;
queryWalletCards();
updateWalletVisibility();
}
+ private void setupWalletPreferenceObserver() {
+ if (mWalletPreferenceObserver == null) {
+ mWalletPreferenceObserver = new ContentObserver(null /* handler */) {
+ @Override
+ public void onChange(boolean selfChange) {
+ mUiExecutor.execute(() -> updateWalletPreference());
+ }
+ };
+
+ mSecureSettings.registerContentObserver(
+ Settings.Secure.getUriFor(QuickAccessWalletClientImpl.SETTING_KEY),
+ false /* notifyForDescendants */,
+ mWalletPreferenceObserver);
+ }
+ }
+
+ private void updateWalletPreference() {
+ mWalletEnabled = mQuickAccessWalletClient.isWalletFeatureAvailable()
+ && mQuickAccessWalletClient.isWalletFeatureAvailableWhenDeviceLocked();
+ }
+
private void queryWalletCards() {
if (!mWalletEnabled || mUiExecutor == null) {
return;
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 069c197..f4710f4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
@@ -140,7 +140,7 @@
*/
private float mQsExpansion;
- private float mEmptyDragAmount;
+ private float mOverStretchAmount;
/**
* Setting if bypass is enabled. If true the clock should always be positioned like it's dark
@@ -181,7 +181,7 @@
int notificationStackHeight, float panelExpansion, int parentHeight,
int keyguardStatusHeight, int userSwitchHeight, int clockPreferredY,
int userSwitchPreferredY, boolean hasCustomClock, boolean hasVisibleNotifs, float dark,
- float emptyDragAmount, boolean bypassEnabled, int unlockedStackScrollerPadding,
+ float overStrechAmount, boolean bypassEnabled, int unlockedStackScrollerPadding,
float qsExpansion, int cutoutTopInset, boolean isSplitShade) {
mMinTopMargin = keyguardStatusBarHeaderHeight + Math.max(mContainerTopPadding,
userSwitchHeight);
@@ -196,7 +196,7 @@
mHasCustomClock = hasCustomClock;
mHasVisibleNotifs = hasVisibleNotifs;
mDarkAmount = dark;
- mEmptyDragAmount = emptyDragAmount;
+ mOverStretchAmount = overStrechAmount;
mBypassEnabled = bypassEnabled;
mUnlockedStackScrollerPadding = unlockedStackScrollerPadding;
mQsExpansion = qsExpansion;
@@ -301,7 +301,7 @@
}
clockYDark = clockY + burnInPreventionOffsetY() + shift;
}
- return (int) (MathUtils.lerp(clockY, clockYDark, darkAmount) + mEmptyDragAmount);
+ return (int) (MathUtils.lerp(clockY, clockYDark, darkAmount) + mOverStretchAmount);
}
private int getUserSwitcherY(float panelExpansion) {
@@ -312,7 +312,7 @@
float shadeExpansion = Interpolators.FAST_OUT_LINEAR_IN.getInterpolation(panelExpansion);
float userSwitchY = MathUtils.lerp(userSwitchYBouncer, userSwitchYRegular, shadeExpansion);
- return (int) (userSwitchY + mEmptyDragAmount);
+ return (int) (userSwitchY + mOverStretchAmount);
}
/**
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 075a0c8..9d8a9bf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -114,6 +114,7 @@
import com.android.systemui.statusbar.GestureRecorder;
import com.android.systemui.statusbar.KeyguardAffordanceView;
import com.android.systemui.statusbar.KeyguardIndicationController;
+import com.android.systemui.statusbar.LockscreenShadeTransitionController;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationShadeDepthController;
import com.android.systemui.statusbar.NotificationShelfController;
@@ -151,6 +152,7 @@
import com.android.systemui.statusbar.policy.KeyguardUserSwitcherView;
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
import com.android.systemui.util.Utils;
+import com.android.systemui.util.settings.SecureSettings;
import com.android.wm.shell.animation.FlingAnimationUtils;
import java.io.FileDescriptor;
@@ -207,7 +209,6 @@
private final ConfigurationListener mConfigurationListener = new ConfigurationListener();
@VisibleForTesting final StatusBarStateListener mStatusBarStateListener =
new StatusBarStateListener();
- private final ExpansionCallback mExpansionCallback = new ExpansionCallback();
private final BiometricUnlockController mBiometricUnlockController;
private final NotificationPanelView mView;
private final VibratorHelper mVibratorHelper;
@@ -312,10 +313,12 @@
// Maximum # notifications to show on Keyguard; extras will be collapsed in an overflow card.
// If there are exactly 1 + mMaxKeyguardNotifications, then still shows all notifications
private final int mMaxKeyguardNotifications;
+ private final LockscreenShadeTransitionController mLockscreenShadeTransitionController;
private boolean mShouldUseSplitNotificationShade;
// Current max allowed keyguard notifications determined by measuring the panel
private int mMaxAllowedKeyguardNotifications;
+ private ViewGroup mPreviewContainer;
private KeyguardAffordanceHelper mAffordanceHelper;
private KeyguardQsUserSwitchController mKeyguardQsUserSwitchController;
private KeyguardUserSwitcherController mKeyguardUserSwitcherController;
@@ -365,7 +368,7 @@
private int mStatusBarMinHeight;
private int mStatusBarHeaderHeightKeyguard;
private int mNotificationsHeaderCollideDistance;
- private float mEmptyDragAmount;
+ private float mOverStretchAmount;
private float mDownX;
private float mDownY;
private int mDisplayCutoutTopInset = 0; // in pixels
@@ -481,7 +484,6 @@
private final CommandQueue mCommandQueue;
private final NotificationLockscreenUserManager mLockscreenUserManager;
private final UserManager mUserManager;
- private final ShadeController mShadeController;
private final MediaDataManager mMediaDataManager;
private NotificationShadeDepthController mDepthController;
private int mDisplayId;
@@ -505,6 +507,39 @@
private float mSectionPadding;
/**
+ * The amount of progress we are currently in if we're transitioning to the full shade.
+ * 0.0f means we're not transitioning yet, while 1 means we're all the way in the full
+ * shade. This value can also go beyond 1.1 when we're overshooting!
+ */
+ private float mTransitioningToFullShadeProgress;
+
+ /**
+ * Position of the qs bottom during the full shade transition. This is needed as the toppadding
+ * can change during state changes, which makes it much harder to do animations
+ */
+ private int mTransitionToFullShadeQSPosition;
+
+ /**
+ * Distance that the full shade transition takes in order for qs to fully transition to the
+ * shade.
+ */
+ private int mDistanceForQSFullShadeTransition;
+
+ /**
+ * The maximum overshoot allowed for the top padding for the full shade transition
+ */
+ private int mMaxOverscrollAmountForDragDown;
+
+ /**
+ * Should we animate the next bounds update
+ */
+ private boolean mAnimateNextNotificationBounds;
+ /**
+ * The delay for the next bounds animation
+ */
+ private long mNotificationBoundsAnimationDelay;
+
+ /**
* Is this a collapse that started on the panel where we should allow the panel to intercept
*/
private boolean mIsPanelCollapseOnQQS;
@@ -521,6 +556,16 @@
private boolean mDelayShowingKeyguardStatusBar;
private boolean mAnimatingQS;
+
+ /**
+ * The end bounds of a clipping animation.
+ */
+ private final Rect mQsClippingAnimationEndBounds = new Rect();
+
+ /**
+ * The animator for the qs clipping bounds.
+ */
+ private ValueAnimator mQsClippingAnimation = null;
private final Rect mKeyguardStatusAreaClipBounds = new Rect();
private int mOldLayoutDirection;
private NotificationShelfController mNotificationShelfController;
@@ -530,6 +575,7 @@
private final QuickAccessWalletClient mQuickAccessWalletClient;
private final Executor mUiExecutor;
+ private final SecureSettings mSecureSettings;
private int mLockScreenMode = KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL;
private KeyguardMediaController mKeyguardMediaController;
@@ -569,7 +615,7 @@
NotificationWakeUpCoordinator coordinator, PulseExpansionHandler pulseExpansionHandler,
DynamicPrivacyController dynamicPrivacyController,
KeyguardBypassController bypassController, FalsingManager falsingManager,
- FalsingCollector falsingCollector, ShadeController shadeController,
+ FalsingCollector falsingCollector,
NotificationLockscreenUserManager notificationLockscreenUserManager,
NotificationEntryManager notificationEntryManager,
KeyguardStateController keyguardStateController,
@@ -591,6 +637,7 @@
KeyguardQsUserSwitchComponent.Factory keyguardQsUserSwitchComponentFactory,
KeyguardUserSwitcherComponent.Factory keyguardUserSwitcherComponentFactory,
KeyguardStatusBarViewComponent.Factory keyguardStatusBarViewComponentFactory,
+ LockscreenShadeTransitionController lockscreenShadeTransitionController,
QSDetailDisplayer qsDetailDisplayer,
NotificationGroupManagerLegacy groupManager,
NotificationIconAreaController notificationIconAreaController,
@@ -605,7 +652,8 @@
QuickAccessWalletClient quickAccessWalletClient,
KeyguardMediaController keyguardMediaController,
PrivacyDotViewController privacyDotViewController,
- @Main Executor uiExecutor) {
+ @Main Executor uiExecutor,
+ SecureSettings secureSettings) {
super(view, falsingManager, dozeLog, keyguardStateController,
(SysuiStatusBarStateController) statusBarStateController, vibratorHelper,
statusBarKeyguardViewManager, latencyTracker, flingAnimationUtilsBuilder.get(),
@@ -657,6 +705,7 @@
mMediaDataManager = mediaDataManager;
mQuickAccessWalletClient = quickAccessWalletClient;
mUiExecutor = uiExecutor;
+ mSecureSettings = secureSettings;
pulseExpansionHandler.setPulseExpandAbortListener(() -> {
if (mQs != null) {
mQs.animateHeaderSlidingOut();
@@ -677,6 +726,8 @@
}
}
};
+ mLockscreenShadeTransitionController = lockscreenShadeTransitionController;
+ lockscreenShadeTransitionController.setNotificationPanelController(this);
mKeyguardStateController.addCallback(keyguardMonitorCallback);
DynamicPrivacyControlListener
dynamicPrivacyControlListener =
@@ -690,7 +741,6 @@
});
mBottomAreaShadeAlphaAnimator.setDuration(160);
mBottomAreaShadeAlphaAnimator.setInterpolator(Interpolators.ALPHA_OUT);
- mShadeController = shadeController;
mLockscreenUserManager = notificationLockscreenUserManager;
mEntryManager = notificationEntryManager;
mConversationNotificationManager = conversationNotificationManager;
@@ -749,14 +799,22 @@
mOnEmptySpaceClickListener);
addTrackingHeadsUpListener(mNotificationStackScrollLayoutController::setTrackingHeadsUp);
mKeyguardBottomArea = mView.findViewById(R.id.keyguard_bottom_area);
+ mPreviewContainer = mView.findViewById(R.id.preview_container);
+ mKeyguardBottomArea.setPreviewContainer(mPreviewContainer);
mLastOrientation = mResources.getConfiguration().orientation;
initBottomArea();
mWakeUpCoordinator.setStackScroller(mNotificationStackScrollLayoutController);
mQsFrame = mView.findViewById(R.id.qs_frame);
- mPulseExpansionHandler.setUp(
- mNotificationStackScrollLayoutController, mExpansionCallback, mShadeController);
+ mPulseExpansionHandler.setUp(mNotificationStackScrollLayoutController,
+ amount -> {
+ float progress = amount / mView.getHeight();
+ float overstretch = Interpolators.getOvershootInterpolation(progress,
+ (float) mMaxOverscrollAmountForDragDown / mView.getHeight(),
+ 0.2f);
+ setOverStrechAmount(overstretch);
+ });
mWakeUpCoordinator.addListener(new NotificationWakeUpCoordinator.WakeUpListener() {
@Override
public void onFullyHiddenChanged(boolean isFullyHidden) {
@@ -812,6 +870,10 @@
com.android.internal.R.dimen.status_bar_height);
mHeadsUpInset = statusbarHeight + mResources.getDimensionPixelSize(
R.dimen.heads_up_status_bar_padding);
+ mDistanceForQSFullShadeTransition = mResources.getDimensionPixelSize(
+ R.dimen.lockscreen_shade_qs_transition_distance);
+ mMaxOverscrollAmountForDragDown = mResources.getDimensionPixelSize(
+ R.dimen.lockscreen_shade_max_top_overshoot);
mScrimCornerRadius = mResources.getDimensionPixelSize(
R.dimen.notification_scrim_corner_radius);
mScreenCornerRadius = mResources.getDimensionPixelSize(
@@ -989,6 +1051,7 @@
mKeyguardBottomArea = (KeyguardBottomAreaView) mLayoutInflater.inflate(
R.layout.keyguard_bottom_area, mView, false);
mKeyguardBottomArea.initFrom(oldBottomArea);
+ mKeyguardBottomArea.setPreviewContainer(mPreviewContainer);
mView.addView(mKeyguardBottomArea, index);
initBottomArea();
mKeyguardIndicationController.setIndicationArea(mKeyguardBottomArea);
@@ -1033,8 +1096,10 @@
mKeyguardBottomArea.setStatusBar(mStatusBar);
mKeyguardBottomArea.setUserSetupComplete(mUserSetupComplete);
mKeyguardBottomArea.setFalsingManager(mFalsingManager);
- mKeyguardBottomArea.initWallet(mQuickAccessWalletClient, mUiExecutor,
- mFeatureFlags.isQuickAccessWalletEnabled());
+
+ if (mFeatureFlags.isQuickAccessWalletEnabled()) {
+ mKeyguardBottomArea.initWallet(mQuickAccessWalletClient, mUiExecutor, mSecureSettings);
+ }
}
private void updateMaxDisplayedNotifications(boolean recompute) {
@@ -1108,58 +1173,28 @@
* showing.
*/
private void positionClockAndNotifications() {
+ positionClockAndNotifications(false /* forceUpdate */);
+ }
+
+ /**
+ * Positions the clock and notifications dynamically depending on how many notifications are
+ * showing.
+ *
+ * @param forceClockUpdate Should the clock be updated even when not on keyguard
+ */
+ private void positionClockAndNotifications(boolean forceClockUpdate) {
boolean animate = mNotificationStackScrollLayoutController.isAddOrRemoveAnimationPending();
- boolean animateClock = animate || mAnimateNextPositionUpdate;
int stackScrollerPadding;
- if (mBarState != KEYGUARD) {
+ boolean onKeyguard = isOnKeyguard();
+ if (onKeyguard || forceClockUpdate) {
+ updateClockAppearance();
+ }
+ if (!onKeyguard) {
stackScrollerPadding = getUnlockedStackScrollerPadding();
} else {
- 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
- .getVisibleNotificationCount() != 0 || mMediaDataManager.hasActiveMedia();
- mKeyguardStatusViewController.setHasVisibleNotifications(hasVisibleNotifications);
- int userIconHeight = mKeyguardQsUserSwitchController != null
- ? mKeyguardQsUserSwitchController.getUserIconHeight() : 0;
- mClockPositionAlgorithm.setup(mStatusBarHeaderHeightKeyguard,
- totalHeight - bottomPadding,
- mNotificationStackScrollLayoutController.getIntrinsicContentHeight(),
- getExpandedFraction(),
- totalHeight,
- mLockScreenMode == KeyguardUpdateMonitor.LOCK_SCREEN_MODE_LAYOUT_1
- ? mKeyguardStatusViewController.getHeight()
- : (int) (mKeyguardStatusViewController.getHeight()
- - mShelfHeight / 2.0f - mDarkIconSize / 2.0f),
- userIconHeight,
- clockPreferredY, userSwitcherPreferredY, hasCustomClock(),
- hasVisibleNotifications, mInterpolatedDarkAmount, mEmptyDragAmount,
- bypassEnabled, getUnlockedStackScrollerPadding(),
- getQsExpansionFraction(),
- mDisplayCutoutTopInset,
- shouldUseSplitNotificationShade(mFeatureFlags, mResources));
- mClockPositionAlgorithm.run(mClockPositionResult);
- mKeyguardStatusViewController.updatePosition(
- mClockPositionResult.clockX, mClockPositionResult.clockY,
- mClockPositionResult.clockScale, animateClock);
- if (mKeyguardQsUserSwitchController != null) {
- mKeyguardQsUserSwitchController.updatePosition(
- mClockPositionResult.clockX,
- mClockPositionResult.userSwitchY,
- animateClock);
- }
- if (mKeyguardUserSwitcherController != null) {
- mKeyguardUserSwitcherController.updatePosition(
- mClockPositionResult.clockX,
- mClockPositionResult.userSwitchY,
- animateClock);
- }
- updateNotificationTranslucency();
- updateClock();
stackScrollerPadding = mClockPositionResult.stackScrollerPaddingExpanded;
}
+
mNotificationStackScrollLayoutController.setIntrinsicPadding(stackScrollerPadding);
mKeyguardBottomArea.setAntiBurnInOffsetX(mClockPositionResult.clockX);
@@ -1169,6 +1204,60 @@
mAnimateNextPositionUpdate = false;
}
+ 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
+ .getVisibleNotificationCount() != 0 || mMediaDataManager.hasActiveMedia();
+ mKeyguardStatusViewController.setHasVisibleNotifications(hasVisibleNotifications);
+ int userIconHeight = mKeyguardQsUserSwitchController != null
+ ? mKeyguardQsUserSwitchController.getUserIconHeight() : 0;
+ float expandedFraction =
+ mKeyguardStatusViewController.isAnimatingScreenOffFromUnlocked() ? 1.0f
+ : getExpandedFraction();
+ float darkamount = mKeyguardStatusViewController.isAnimatingScreenOffFromUnlocked() ? 1.0f
+ : mInterpolatedDarkAmount;
+ mClockPositionAlgorithm.setup(mStatusBarHeaderHeightKeyguard,
+ totalHeight - bottomPadding,
+ mNotificationStackScrollLayoutController.getIntrinsicContentHeight(),
+ expandedFraction,
+ totalHeight,
+ mLockScreenMode == KeyguardUpdateMonitor.LOCK_SCREEN_MODE_LAYOUT_1
+ ? mKeyguardStatusViewController.getHeight()
+ : (int) (mKeyguardStatusViewController.getHeight()
+ - mShelfHeight / 2.0f - mDarkIconSize / 2.0f),
+ userIconHeight,
+ clockPreferredY, userSwitcherPreferredY, hasCustomClock(),
+ hasVisibleNotifications, darkamount, mOverStretchAmount,
+ bypassEnabled, getUnlockedStackScrollerPadding(),
+ computeQsExpansionFraction(),
+ mDisplayCutoutTopInset,
+ shouldUseSplitNotificationShade(mFeatureFlags, mResources));
+ mClockPositionAlgorithm.run(mClockPositionResult);
+ boolean animate = mNotificationStackScrollLayoutController.isAddOrRemoveAnimationPending();
+ boolean animateClock = animate || mAnimateNextPositionUpdate;
+ mKeyguardStatusViewController.updatePosition(
+ mClockPositionResult.clockX, mClockPositionResult.clockY,
+ mClockPositionResult.clockScale, animateClock);
+ if (mKeyguardQsUserSwitchController != null) {
+ mKeyguardQsUserSwitchController.updatePosition(
+ mClockPositionResult.clockX,
+ mClockPositionResult.userSwitchY,
+ animateClock);
+ }
+ if (mKeyguardUserSwitcherController != null) {
+ mKeyguardUserSwitcherController.updatePosition(
+ mClockPositionResult.clockX,
+ mClockPositionResult.userSwitchY,
+ animateClock);
+ }
+ updateNotificationTranslucency();
+ updateClock();
+ }
+
/**
* @return the padding of the stackscroller when unlocked
*/
@@ -1600,7 +1689,7 @@
private boolean flingExpandsQs(float vel) {
if (Math.abs(vel) < mFlingAnimationUtils.getMinVelocityPxPerSecond()) {
- return getQsExpansionFraction() > 0.5f;
+ return computeQsExpansionFraction() > 0.5f;
} else {
return vel > 0;
}
@@ -1613,7 +1702,7 @@
return !mQsTouchAboveFalsingThreshold;
}
- private float getQsExpansionFraction() {
+ private float computeQsExpansionFraction() {
return Math.min(
1f, (mQsExpansionHeight - mQsMinExpansionHeight) / (mQsMaxExpansionHeight
- mQsMinExpansionHeight));
@@ -1838,7 +1927,7 @@
mQsTracking = false;
mTrackingPointer = -1;
trackMovement(event);
- float fraction = getQsExpansionFraction();
+ float fraction = computeQsExpansionFraction();
if (fraction != 0f || y >= mInitialTouchY) {
flingQsWithCurrentVelocity(y,
event.getActionMasked() == MotionEvent.ACTION_CANCEL);
@@ -2044,18 +2133,19 @@
protected void updateQsExpansion() {
if (mQs == null) return;
- float qsExpansionFraction = getQsExpansionFraction();
+ float qsExpansionFraction = computeQsExpansionFraction();
mQs.setQsExpansion(qsExpansionFraction, getHeaderTranslation());
mMediaHierarchyManager.setQsExpansion(qsExpansionFraction);
int qsPanelBottomY = calculateQsBottomPosition(qsExpansionFraction);
mScrimController.setQsPosition(qsExpansionFraction, qsPanelBottomY);
+ setQSClippingBounds();
mNotificationStackScrollLayoutController.setQsExpansionFraction(qsExpansionFraction);
mDepthController.setQsPanelExpansion(qsExpansionFraction);
}
private Runnable mOnStackYChanged = () -> {
if (mQs != null) {
- setNotificationBounds();
+ setQSClippingBounds();
}
};
@@ -2063,57 +2153,121 @@
* Updates scrim bounds, QS clipping, and KSV clipping as well based on the bounds of the shade
* and QS state.
*/
- private void setNotificationBounds() {
+ private void setQSClippingBounds() {
int top = 0;
int bottom = 0;
int left = 0;
int right = 0;
- final int qsPanelBottomY = calculateQsBottomPosition(getQsExpansionFraction());
- final boolean visible = (getQsExpansionFraction() > 0 || qsPanelBottomY > 0)
+ final int qsPanelBottomY = calculateQsBottomPosition(computeQsExpansionFraction());
+ final boolean visible = (computeQsExpansionFraction() > 0 || qsPanelBottomY > 0)
&& !mShouldUseSplitNotificationShade;
- final float notificationTop = mAmbientState.getStackY() - mAmbientState.getScrollY();
setQsExpansionEnabled(mAmbientState.getScrollY() == 0);
- int radius = mScrimCornerRadius;
if (!mShouldUseSplitNotificationShade) {
- top = (int) (isOnKeyguard() ? Math.min(qsPanelBottomY, notificationTop)
- : notificationTop);
+ if (mTransitioningToFullShadeProgress > 0.0f) {
+ // If we're transitioning, let's use the actual value. The else case
+ // can be wrong during transitions when waiting for the keyguard to unlock
+ top = mTransitionToFullShadeQSPosition;
+ } else {
+ float notificationTop = getQSEdgePosition();
+ top = (int) (isOnKeyguard() ? Math.min(qsPanelBottomY, notificationTop)
+ : notificationTop);
+ }
bottom = getView().getBottom();
left = getView().getLeft();
right = getView().getRight();
- radius = (int) MathUtils.lerp(mScreenCornerRadius, mScrimCornerRadius,
- Math.min(top / (float) mScrimCornerRadius, 1f));
} else if (qsPanelBottomY > 0) { // so bounds are empty on lockscreen
top = Math.min(qsPanelBottomY, mSplitShadeNotificationsTopPadding);
bottom = mNotificationStackScrollLayoutController.getHeight();
left = mNotificationStackScrollLayoutController.getLeft();
right = mNotificationStackScrollLayoutController.getRight();
}
+ applyQSClippingBounds(left, top, right, bottom, visible);
+ }
- // Fancy clipping for quick settings
- if (mQs != null) {
- mQs.setFancyClipping(top, bottom, radius, visible);
+ private void applyQSClippingBounds(int left, int top, int right, int bottom,
+ boolean visible) {
+ 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);
+ }
+ } else {
+ mQsClippingAnimationEndBounds.set(left, top, right, bottom);
+ final int startLeft = mKeyguardStatusAreaClipBounds.left;
+ final int startTop = mKeyguardStatusAreaClipBounds.top;
+ final int startRight = mKeyguardStatusAreaClipBounds.right;
+ final int startBottom = mKeyguardStatusAreaClipBounds.bottom;
+ mQsClippingAnimation = ValueAnimator.ofFloat(0.0f, 1.0f);
+ mQsClippingAnimation.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
+ mQsClippingAnimation.setDuration(
+ StackStateAnimator.ANIMATION_DURATION_GO_TO_FULL_SHADE);
+ mQsClippingAnimation.setStartDelay(mNotificationBoundsAnimationDelay);
+ mQsClippingAnimation.addUpdateListener(animation -> {
+ float fraction = animation.getAnimatedFraction();
+ int animLeft = (int) MathUtils.lerp(startLeft,
+ mQsClippingAnimationEndBounds.left, fraction);
+ int animTop = (int) MathUtils.lerp(startTop,
+ mQsClippingAnimationEndBounds.top, fraction);
+ int animRight = (int) MathUtils.lerp(startRight,
+ mQsClippingAnimationEndBounds.right, fraction);
+ int animBottom = (int) MathUtils.lerp(startBottom,
+ mQsClippingAnimationEndBounds.bottom, fraction);
+ applyQSClippingImmediately(animLeft, animTop, animRight, animBottom,
+ visible /* visible */);
+ });
+ mQsClippingAnimation.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mQsClippingAnimation = null;
+ }
+ });
+ mQsClippingAnimation.start();
}
+ mAnimateNextNotificationBounds = false;
+ mNotificationBoundsAnimationDelay = 0;
+ }
+
+ private void applyQSClippingImmediately(int left, int top, int right, int bottom,
+ boolean visible) {
+ // Fancy clipping for quick settings
+ int radius = mScrimCornerRadius;
if (!mShouldUseSplitNotificationShade) {
// The padding on this area is large enough that we can use a cheaper clipping strategy
mKeyguardStatusAreaClipBounds.set(left, top, right, bottom);
mKeyguardStatusViewController.setClipBounds(visible
? mKeyguardStatusAreaClipBounds : null);
+ radius = (int) MathUtils.lerp(mScreenCornerRadius, mScrimCornerRadius,
+ Math.min(top / (float) mScrimCornerRadius, 1f));
+ }
+ if (mQs != null) {
+ mQs.setFancyClipping(top, bottom, radius, visible);
}
mScrimController.setNotificationsBounds(left, top, right, bottom);
mScrimController.setScrimCornerRadius(radius);
}
+ private float getQSEdgePosition() {
+ // TODO: replace StackY with unified calculation
+ return mAmbientState.getStackY() - mAmbientState.getScrollY();
+ }
+
private int calculateQsBottomPosition(float qsExpansionFraction) {
- int qsBottomY = (int) getHeaderTranslation() + mQs.getQsMinExpansionHeight();
- if (qsExpansionFraction != 0.0) {
- qsBottomY = (int) MathUtils.lerp(
- qsBottomY, mQs.getDesiredHeight(), qsExpansionFraction);
+ if (mTransitioningToFullShadeProgress > 0.0f) {
+ return mTransitionToFullShadeQSPosition;
+ } else {
+ int qsBottomY = (int) getHeaderTranslation() + mQs.getQsMinExpansionHeight();
+ if (qsExpansionFraction != 0.0) {
+ qsBottomY = (int) MathUtils.lerp(
+ qsBottomY, mQs.getDesiredHeight(), qsExpansionFraction);
+ }
+ // to account for shade overshooting animation, see setSectionPadding method
+ if (mSectionPadding > 0) qsBottomY += mSectionPadding;
+ return qsBottomY;
}
- // to account for shade overshooting animation, see setSectionPadding method
- if (mSectionPadding > 0) qsBottomY += mSectionPadding;
- return qsBottomY;
}
private String determineAccessibilityPaneTitle() {
@@ -2157,7 +2311,7 @@
// from a scrolled quick settings.
return MathUtils.lerp((float) getKeyguardNotificationStaticPadding(),
(float) (mQsMaxExpansionHeight + mQsNotificationTopPadding),
- getQsExpansionFraction());
+ computeQsExpansionFraction());
} else {
return mQsExpansionHeight + mQsNotificationTopPadding;
}
@@ -2194,15 +2348,65 @@
}
}
-
private void updateQSPulseExpansion() {
if (mQs != null) {
- mQs.setShowCollapsedOnKeyguard(
+ mQs.setPulseExpanding(
mKeyguardShowing && mKeyguardBypassController.getBypassEnabled()
&& mNotificationStackScrollLayoutController.isPulseExpanding());
}
}
+ /**
+ * Set the amount of pixels we have currently dragged down if we're transitioning to the full
+ * shade. 0.0f means we're not transitioning yet.
+ */
+ public void setTransitionToFullShadeAmount(float pxAmount, boolean animate, long delay) {
+ mAnimateNextNotificationBounds = animate && !mShouldUseSplitNotificationShade;
+ mNotificationBoundsAnimationDelay = delay;
+ float progress = MathUtils.saturate(pxAmount / mView.getHeight());
+
+ float endPosition = 0;
+ if (pxAmount > 0.0f) {
+ if (mNotificationStackScrollLayoutController.getVisibleNotificationCount() == 0
+ && !mMediaDataManager.hasActiveMedia()) {
+ // No notifications are visible, let's animate to the height of qs instead
+ if (mQs != null) {
+ // Let's interpolate to the header height
+ endPosition = mQs.getHeader().getHeight();
+ }
+ } else {
+ // Interpolating to the new bottom edge position!
+ endPosition = getQSEdgePosition() - mOverStretchAmount;
+
+ // If we have media, we need to put the boundary below it, as the media header
+ // still uses the space during the transition.
+ endPosition +=
+ mNotificationStackScrollLayoutController.getFullShadeTransitionInset();
+ }
+ }
+
+ // Calculate the overshoot amount such that we're reaching the target after our desired
+ // distance, but only reach it fully once we drag a full shade length.
+ float transitionProgress = 0;
+ if (endPosition != 0 && progress != 0) {
+ transitionProgress = Interpolators.getOvershootInterpolation(progress,
+ mMaxOverscrollAmountForDragDown / endPosition,
+ (float) mDistanceForQSFullShadeTransition / (float) mView.getHeight());
+ }
+ mTransitioningToFullShadeProgress = transitionProgress;
+
+ int position = (int) MathUtils.lerp((float) 0, endPosition,
+ mTransitioningToFullShadeProgress);
+ if (mTransitioningToFullShadeProgress > 0.0f) {
+ // we want at least 1 pixel otherwise the panel won't be clipped
+ position = Math.max(1, position);
+ }
+ float overStretchAmount = Math.max(position - endPosition, 0.0f);
+ setOverStrechAmount(overStretchAmount);
+ mTransitionToFullShadeQSPosition = position;
+ updateQsExpansion();
+ }
+
private void trackMovement(MotionEvent event) {
if (mQsVelocityTracker != null) mQsVelocityTracker.addMovement(event);
}
@@ -2626,7 +2830,7 @@
if (!mKeyguardShowing) {
return;
}
- float alphaQsExpansion = 1 - Math.min(1, getQsExpansionFraction() * 2);
+ float alphaQsExpansion = 1 - Math.min(1, computeQsExpansionFraction() * 2);
float newAlpha = Math.min(getKeyguardContentsAlpha(), alphaQsExpansion)
* mKeyguardStatusBarAnimateAlpha;
newAlpha *= 1.0f - mKeyguardHeadsUpShowingAmount;
@@ -2649,7 +2853,7 @@
float expansionAlpha = MathUtils.map(
isUnlockHintRunning() ? 0 : KeyguardBouncer.ALPHA_EXPANSION_THRESHOLD, 1f, 0f, 1f,
getExpandedFraction());
- float alpha = Math.min(expansionAlpha, 1 - getQsExpansionFraction());
+ float alpha = Math.min(expansionAlpha, 1 - computeQsExpansionFraction());
alpha *= mBottomAreaShadeAlpha;
mKeyguardBottomArea.setAffordanceAlpha(alpha);
mKeyguardBottomArea.setImportantForAccessibility(
@@ -2671,7 +2875,7 @@
float expansionAlpha = MathUtils.map(
isUnlockHintRunning() ? 0 : KeyguardBouncer.ALPHA_EXPANSION_THRESHOLD, 1f, 0f, 1f,
getExpandedFraction());
- float alpha = Math.min(expansionAlpha, 1 - getQsExpansionFraction());
+ float alpha = Math.min(expansionAlpha, 1 - computeQsExpansionFraction());
mBigClockContainer.setAlpha(alpha);
}
@@ -3223,6 +3427,7 @@
mHeightListener.onQsHeightChanged();
}
});
+ mLockscreenShadeTransitionController.setQS(mQs);
mNotificationStackScrollLayoutController.setQsContainer((ViewGroup) mQs.getView());
updateQsExpansion();
}
@@ -3460,9 +3665,9 @@
StatusBar statusBar,
NotificationShelfController notificationShelfController) {
setStatusBar(statusBar);
- mNotificationStackScrollLayoutController.setNotificationPanelController(this);
mNotificationStackScrollLayoutController.setShelfController(notificationShelfController);
mNotificationShelfController = notificationShelfController;
+ mLockscreenShadeTransitionController.bindController(notificationShelfController);
updateMaxDisplayedNotifications(true);
}
@@ -3513,10 +3718,6 @@
return new OnLayoutChangeListener();
}
- public void setEmptyDragAmount(float amount) {
- mExpansionCallback.setEmptyDragAmount(amount);
- }
-
@Override
protected TouchHandler createTouchHandler() {
return new TouchHandler() {
@@ -3985,7 +4186,7 @@
mClockPositionResult.clockX,
mClockPositionResult.clockYFullyDozing,
mClockPositionResult.clockScale,
- false);
+ false /* animate */);
}
mKeyguardStatusViewController.setKeyguardStatusViewVisibility(
@@ -4001,11 +4202,7 @@
if (oldState == KEYGUARD && (goingToFullShade
|| statusBarState == StatusBarState.SHADE_LOCKED)) {
animateKeyguardStatusBarOut();
- long
- delay =
- mBarState == StatusBarState.SHADE_LOCKED ? 0
- : mKeyguardStateController.calculateGoingToFullShadeDelay();
- mQs.animateHeaderSlidingIn(delay);
+ updateQSMinHeight();
} else if (oldState == StatusBarState.SHADE_LOCKED
&& statusBarState == KEYGUARD) {
animateKeyguardStatusBarIn(StackStateAnimator.ANIMATION_DURATION_STANDARD);
@@ -4052,11 +4249,12 @@
}
}
- private class ExpansionCallback implements PulseExpansionHandler.ExpansionCallback {
- public void setEmptyDragAmount(float amount) {
- mEmptyDragAmount = amount * 0.2f;
- positionClockAndNotifications();
- }
+ /**
+ * Sets the overstretch amount in raw pixels when dragging down.
+ */
+ public void setOverStrechAmount(float amount) {
+ mOverStretchAmount = amount;
+ positionClockAndNotifications(true /* forceUpdate */);
}
private class OnAttachStateChangeListener implements View.OnAttachStateChangeListener {
@@ -4071,6 +4269,7 @@
// force a call to onThemeChanged
mConfigurationListener.onThemeChanged();
mFalsingManager.addTapListener(mFalsingTapListener);
+ mKeyguardIndicationController.init();
}
@Override
@@ -4102,11 +4301,7 @@
// Calculate quick setting heights.
int oldMaxHeight = mQsMaxExpansionHeight;
if (mQs != null) {
- float previousMin = mQsMinExpansionHeight;
- mQsMinExpansionHeight = mKeyguardShowing ? 0 : mQs.getQsMinExpansionHeight();
- if (mQsExpansionHeight == previousMin) {
- mQsExpansionHeight = mQsMinExpansionHeight;
- }
+ updateQSMinHeight();
mQsMaxExpansionHeight = mQs.getDesiredHeight();
mNotificationStackScrollLayoutController.setMaxTopPadding(
mQsMaxExpansionHeight + mQsNotificationTopPadding);
@@ -4148,6 +4343,14 @@
}
}
+ private void updateQSMinHeight() {
+ float previousMin = mQsMinExpansionHeight;
+ mQsMinExpansionHeight = mKeyguardShowing ? 0 : mQs.getQsMinExpansionHeight();
+ if (mQsExpansionHeight == previousMin) {
+ mQsExpansionHeight = mQsMinExpansionHeight;
+ }
+ }
+
private class DebugDrawable extends Drawable {
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java
index 4d70237..7f4dabd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java
@@ -34,15 +34,14 @@
import android.view.ViewGroup;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.ExpandHelper;
import com.android.systemui.R;
import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.dock.DockManager;
import com.android.systemui.doze.DozeLog;
-import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.DragDownHelper;
+import com.android.systemui.statusbar.LockscreenShadeTransitionController;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationShadeDepthController;
import com.android.systemui.statusbar.NotificationShadeWindowController;
@@ -73,7 +72,6 @@
private final DynamicPrivacyController mDynamicPrivacyController;
private final KeyguardBypassController mBypassController;
private final PluginManager mPluginManager;
- private final FalsingManager mFalsingManager;
private final FalsingCollector mFalsingCollector;
private final TunerService mTunerService;
private final NotificationLockscreenUserManager mNotificationLockscreenUserManager;
@@ -87,6 +85,7 @@
private final ShadeController mShadeController;
private final NotificationShadeDepthController mDepthController;
private final NotificationStackScrollLayoutController mNotificationStackScrollLayoutController;
+ private final LockscreenShadeTransitionController mLockscreenShadeTransitionController;
private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
private GestureDetector mGestureDetector;
@@ -119,7 +118,7 @@
PulseExpansionHandler pulseExpansionHandler,
DynamicPrivacyController dynamicPrivacyController,
KeyguardBypassController bypassController,
- FalsingManager falsingManager,
+ LockscreenShadeTransitionController transitionController,
FalsingCollector falsingCollector,
PluginManager pluginManager,
TunerService tunerService,
@@ -143,7 +142,7 @@
mPulseExpansionHandler = pulseExpansionHandler;
mDynamicPrivacyController = dynamicPrivacyController;
mBypassController = bypassController;
- mFalsingManager = falsingManager;
+ mLockscreenShadeTransitionController = transitionController;
mFalsingCollector = falsingCollector;
mPluginManager = pluginManager;
mTunerService = tunerService;
@@ -406,12 +405,7 @@
}
});
- ExpandHelper.Callback expandHelperCallback = mStackScrollLayout.getExpandHelperCallback();
- DragDownHelper.DragDownCallback dragDownCallback = mStackScrollLayout.getDragDownCallback();
- setDragDownHelper(
- new DragDownHelper(
- mView.getContext(), mView, expandHelperCallback,
- dragDownCallback, mFalsingManager, mFalsingCollector));
+ setDragDownHelper(mLockscreenShadeTransitionController.getTouchHelper());
mDepthController.setRoot(mView);
mNotificationPanelViewController.addExpansionListener(mDepthController);
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 c34fa2f..7c63763 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -28,6 +28,7 @@
import android.os.Trace;
import android.util.Log;
import android.util.MathUtils;
+import android.util.Pair;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.animation.DecelerateInterpolator;
@@ -42,10 +43,10 @@
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.settingslib.Utils;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.DejankUtils;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
+import com.android.systemui.animation.Interpolators;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dock.DockManager;
@@ -98,6 +99,18 @@
public static final int OPAQUE = 2;
private boolean mClipsQsScrim;
+ /**
+ * The amount of progress we are currently in if we're transitioning to the full shade.
+ * 0.0f means we're not transitioning yet, while 1 means we're all the way in the full
+ * shade.
+ */
+ private float mTransitionToFullShadeProgress;
+
+ /**
+ * If we're currently transitioning to the full shade.
+ */
+ private boolean mTransitioningToFullShade;
+
@IntDef(prefix = {"VISIBILITY_"}, value = {
TRANSPARENT,
SEMI_TRANSPARENT,
@@ -357,7 +370,7 @@
+ mInFrontAlpha + ", back: " + mBehindAlpha + ", notif: "
+ mNotificationsAlpha);
}
- applyExpansionToAlpha();
+ applyStateToAlpha();
// Scrim might acquire focus when user is navigating with a D-pad or a keyboard.
// We need to disable focus otherwise AOD would end up with a gray overlay.
@@ -499,17 +512,47 @@
if (!(relevantState && mExpansionAffectsAlpha)) {
return;
}
- applyAndDispatchExpansion();
+ applyAndDispatchState();
}
}
/**
+ * Set the amount of progress we are currently in if we're transitioning to the full shade.
+ * 0.0f means we're not transitioning yet, while 1 means we're all the way in the full
+ * shade.
+ */
+ public void setTransitionToFullShadeProgress(float progress) {
+ if (progress != mTransitionToFullShadeProgress) {
+ mTransitionToFullShadeProgress = progress;
+ setTransitionToFullShade(progress > 0.0f);
+ applyAndDispatchState();
+ }
+ }
+
+ /**
+ * Set if we're currently transitioning to the full shade
+ */
+ private void setTransitionToFullShade(boolean transitioning) {
+ if (transitioning != mTransitioningToFullShade) {
+ mTransitioningToFullShade = transitioning;
+ if (transitioning) {
+ // Let's make sure the shade locked is ready
+ ScrimState.SHADE_LOCKED.prepare(mState);
+ }
+ }
+ }
+
+
+ /**
* Set bounds for notifications background, all coordinates are absolute
*/
public void setNotificationsBounds(float left, float top, float right, float bottom) {
- mNotificationsScrim.setDrawableBounds(left, top, right, bottom);
if (mClipsQsScrim) {
+ // "top - 1" to have 1 px of scrims overlap, see: b/186644628
+ mNotificationsScrim.setDrawableBounds(left, top - 1, right, bottom);
mScrimBehind.setBottomEdgePosition((int) top);
+ } else {
+ mNotificationsScrim.setDrawableBounds(left, top, right, bottom);
}
}
@@ -534,7 +577,7 @@
if (!(relevantState && mExpansionAffectsAlpha)) {
return;
}
- applyAndDispatchExpansion();
+ applyAndDispatchState();
}
}
@@ -553,6 +596,11 @@
if (mScrimBehind != null) {
mScrimBehind.enableBottomEdgeConcave(mClipsQsScrim);
}
+ if (mState != ScrimState.UNINITIALIZED) {
+ // the clipScrimState has changed, let's reprepare ourselves
+ mState.prepare(mState);
+ applyAndDispatchState();
+ }
}
@VisibleForTesting
@@ -583,7 +631,7 @@
}
}
- private void applyExpansionToAlpha() {
+ private void applyStateToAlpha() {
if (!mExpansionAffectsAlpha) {
return;
}
@@ -608,47 +656,40 @@
mInFrontAlpha = 0;
} else if (mState == ScrimState.KEYGUARD || mState == ScrimState.SHADE_LOCKED
|| mState == ScrimState.PULSING) {
- // Either darken of make the scrim transparent when you
- // pull down the shade
- float interpolatedFract = getInterpolatedFraction();
- float stateBehind = mClipsQsScrim ? mState.getNotifAlpha() : mState.getBehindAlpha();
- float backAlpha;
- if (mDarkenWhileDragging) {
- backAlpha = MathUtils.lerp(mDefaultScrimAlpha, stateBehind,
- interpolatedFract);
- } else {
- backAlpha = MathUtils.lerp(0 /* start */, stateBehind,
- interpolatedFract);
+ Pair<Integer, Float> result = calculateBackStateForState(mState);
+ int behindTint = result.first;
+ float behindAlpha = result.second;
+ if (mTransitionToFullShadeProgress > 0.0f) {
+ Pair<Integer, Float> shadeResult = calculateBackStateForState(
+ ScrimState.SHADE_LOCKED);
+ behindAlpha = MathUtils.lerp(behindAlpha, shadeResult.second,
+ mTransitionToFullShadeProgress);
+ behindTint = ColorUtils.blendARGB(behindTint, shadeResult.first,
+ mTransitionToFullShadeProgress);
}
mInFrontAlpha = mState.getFrontAlpha();
- int backTint;
if (mClipsQsScrim) {
- backTint = ColorUtils.blendARGB(ScrimState.BOUNCER.getNotifTint(),
- mState.getNotifTint(), interpolatedFract);
- } else {
- backTint = ColorUtils.blendARGB(ScrimState.BOUNCER.getBehindTint(),
- mState.getBehindTint(), interpolatedFract);
- }
- if (mQsExpansion > 0) {
- backAlpha = MathUtils.lerp(backAlpha, mDefaultScrimAlpha, mQsExpansion);
- int stateTint = mClipsQsScrim ? ScrimState.SHADE_LOCKED.getNotifTint()
- : ScrimState.SHADE_LOCKED.getBehindTint();
- backTint = ColorUtils.blendARGB(backTint, stateTint, mQsExpansion);
- }
- if (mClipsQsScrim) {
- mNotificationsAlpha = backAlpha;
- mNotificationsTint = backTint;
+ mNotificationsAlpha = behindAlpha;
+ mNotificationsTint = behindTint;
mBehindAlpha = 1;
mBehindTint = Color.BLACK;
} else {
- mBehindAlpha = backAlpha;
+ mBehindAlpha = behindAlpha;
if (mState == ScrimState.SHADE_LOCKED) {
// going from KEYGUARD to SHADE_LOCKED state
mNotificationsAlpha = getInterpolatedFraction();
} else {
mNotificationsAlpha = Math.max(1.0f - getInterpolatedFraction(), mQsExpansion);
}
- mBehindTint = backTint;
+ if (mState == ScrimState.KEYGUARD && mTransitionToFullShadeProgress > 0.0f) {
+ // Interpolate the notification alpha when transitioning!
+ mNotificationsAlpha = MathUtils.lerp(
+ mNotificationsAlpha,
+ getInterpolatedFraction(),
+ mTransitionToFullShadeProgress);
+ }
+ mNotificationsTint = mState.getNotifTint();
+ mBehindTint = behindTint;
}
}
if (isNaN(mBehindAlpha) || isNaN(mInFrontAlpha) || isNaN(mNotificationsAlpha)) {
@@ -658,8 +699,39 @@
}
}
- private void applyAndDispatchExpansion() {
- applyExpansionToAlpha();
+ private Pair<Integer, Float> calculateBackStateForState(ScrimState state) {
+ // Either darken of make the scrim transparent when you
+ // pull down the shade
+ float interpolatedFract = getInterpolatedFraction();
+ float stateBehind = mClipsQsScrim ? state.getNotifAlpha() : state.getBehindAlpha();
+ float behindAlpha;
+ int behindTint;
+ if (mDarkenWhileDragging) {
+ behindAlpha = MathUtils.lerp(mDefaultScrimAlpha, stateBehind,
+ interpolatedFract);
+ } else {
+ behindAlpha = MathUtils.lerp(0 /* start */, stateBehind,
+ interpolatedFract);
+ }
+ if (mClipsQsScrim) {
+ behindTint = ColorUtils.blendARGB(ScrimState.BOUNCER.getNotifTint(),
+ state.getNotifTint(), interpolatedFract);
+ } else {
+ behindTint = ColorUtils.blendARGB(ScrimState.BOUNCER.getBehindTint(),
+ state.getBehindTint(), interpolatedFract);
+ }
+ if (mQsExpansion > 0) {
+ behindAlpha = MathUtils.lerp(behindAlpha, mDefaultScrimAlpha, mQsExpansion);
+ int stateTint = mClipsQsScrim ? ScrimState.SHADE_LOCKED.getNotifTint()
+ : ScrimState.SHADE_LOCKED.getBehindTint();
+ behindTint = ColorUtils.blendARGB(behindTint, stateTint, mQsExpansion);
+ }
+ return new Pair<>(behindTint, behindAlpha);
+ }
+
+
+ private void applyAndDispatchState() {
+ applyStateToAlpha();
if (mUpdatePending) {
return;
}
@@ -780,7 +852,7 @@
setScrimAlpha(mScrimForBubble, mBubbleAlpha);
}
// The animation could have all already finished, let's call onFinished just in case
- onFinished();
+ onFinished(mState);
dispatchScrimsVisible();
}
@@ -847,7 +919,6 @@
Trace.traceCounter(Trace.TRACE_TAG_APP, getScrimName(scrimView) + "_tint",
Color.alpha(tint));
-
scrimView.setTint(tint);
scrimView.setViewAlpha(alpha);
} else {
@@ -878,12 +949,13 @@
anim.setStartDelay(mAnimationDelay);
anim.setDuration(mAnimationDuration);
anim.addListener(new AnimatorListenerAdapter() {
- private Callback lastCallback = mCallback;
+ private final ScrimState mLastState = mState;
+ private final Callback mLastCallback = mCallback;
@Override
public void onAnimationEnd(Animator animation) {
scrim.setTag(TAG_KEY_ANIM, null);
- onFinished(lastCallback);
+ onFinished(mLastCallback, mLastState);
dispatchScrimsVisible();
}
@@ -937,11 +1009,14 @@
return true;
}
- private void onFinished() {
- onFinished(mCallback);
+ /**
+ * @param state that finished
+ */
+ private void onFinished(ScrimState state) {
+ onFinished(mCallback, state);
}
- private void onFinished(Callback callback) {
+ private void onFinished(Callback callback, ScrimState state) {
if (mPendingFrameCallback != null) {
// No animations can finish while we're waiting on the blanking to finish
return;
@@ -973,7 +1048,7 @@
// When unlocking with fingerprint, we'll fade the scrims from black to transparent.
// At the end of the animation we need to remove the tint.
- if (mState == ScrimState.UNLOCKED) {
+ if (state == ScrimState.UNLOCKED) {
mInFrontTint = Color.TRANSPARENT;
mBehindTint = mState.getBehindTint();
mNotificationsTint = mState.getNotifTint();
@@ -1195,7 +1270,7 @@
public void setExpansionAffectsAlpha(boolean expansionAffectsAlpha) {
mExpansionAffectsAlpha = expansionAffectsAlpha;
if (expansionAffectsAlpha) {
- applyAndDispatchExpansion();
+ applyAndDispatchState();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeController.java
index 2fa6795..2d41e5e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeController.java
@@ -14,8 +14,6 @@
package com.android.systemui.statusbar.phone;
-import android.view.View;
-
import com.android.systemui.statusbar.StatusBarState;
/**
@@ -78,15 +76,6 @@
void runPostCollapseRunnables();
/**
- * If secure with redaction: Show bouncer, go to unlocked shade.
- *
- * <p>If secure without redaction or no security: Go to {@link StatusBarState#SHADE_LOCKED}.</p>
- *
- * @param startingChild The view to expand after going to the shade.
- */
- void goToLockedShade(View startingChild);
-
- /**
* Close the shade if it was open
*
* @return true if the shade was open, else false
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeControllerImpl.java
index a930a89..d4458e2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeControllerImpl.java
@@ -17,7 +17,6 @@
package com.android.systemui.statusbar.phone;
import android.util.Log;
-import android.view.View;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
@@ -182,12 +181,6 @@
}
@Override
- public void goToLockedShade(View startingChild) {
- // TODO: Move this code out of StatusBar into ShadeController.
- getStatusBar().goToLockedShade(startingChild);
- }
-
- @Override
public boolean collapsePanel() {
if (!getNotificationPanelViewController().isFullyCollapsed()) {
// close the shade if it was open
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 9d656f4..9c6d623 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -194,6 +194,7 @@
import com.android.systemui.statusbar.KeyguardIndicationController;
import com.android.systemui.statusbar.LiftReveal;
import com.android.systemui.statusbar.LightRevealScrim;
+import com.android.systemui.statusbar.LockscreenShadeTransitionController;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.NotificationPresenter;
@@ -347,6 +348,8 @@
ONLY_CORE_APPS = onlyCoreApps;
}
+ private LockscreenShadeTransitionController mLockscreenShadeTransitionController;
+
public interface ExpansionChangedListener {
void onExpansionChanged(float expansion, boolean expanded);
}
@@ -438,9 +441,6 @@
KeyguardIndicationController mKeyguardIndicationController;
- // RemoteInputView to be activated after unlock
- private View mPendingRemoteInputView;
-
private final RemoteInputQuickSettingsDisabler mRemoteInputQuickSettingsDisabler;
private View mReportRejectedTouch;
@@ -650,12 +650,6 @@
private final ScreenLifecycle mScreenLifecycle;
private final WakefulnessLifecycle mWakefulnessLifecycle;
- private final View.OnClickListener mGoToLockedShadeListener = v -> {
- if (mState == StatusBarState.KEYGUARD) {
- wakeUpIfDozing(SystemClock.uptimeMillis(), v, "SHADE_CLICK");
- goToLockedShade(null);
- }
- };
private boolean mNoAnimationOnNextBarModeChange;
private final SysuiStatusBarStateController mStatusBarStateController;
@@ -798,6 +792,7 @@
OngoingCallController ongoingCallController,
SystemStatusAnimationScheduler animationScheduler,
StatusBarLocationPublisher locationPublisher,
+ LockscreenShadeTransitionController lockscreenShadeTransitionController,
FeatureFlags featureFlags,
KeyguardUnlockAnimationController keyguardUnlockAnimationController) {
super(context);
@@ -882,6 +877,8 @@
mAnimationScheduler = animationScheduler;
mStatusBarLocationPublisher = locationPublisher;
mFeatureFlags = featureFlags;
+ mLockscreenShadeTransitionController = lockscreenShadeTransitionController;
+ lockscreenShadeTransitionController.setStatusbar(this);
mExpansionChangedListeners = new ArrayList<>();
@@ -909,6 +906,8 @@
mBroadcastDispatcher.registerReceiver(mTaskbarChangeReceiver, filter);
}
+ mKeyguardIndicationController.init();
+
mColorExtractor.addOnColorsChangedListener(this);
mStatusBarStateController.addCallback(this,
SysuiStatusBarStateController.RANK_STATUS_BAR);
@@ -1420,7 +1419,8 @@
mDozeScrimController, mScrimController, mNotificationShadeWindowController,
mDynamicPrivacyController, mKeyguardStateController,
mKeyguardIndicationController,
- this /* statusBar */, mShadeController, mCommandQueue, mInitController,
+ this /* statusBar */, mShadeController,
+ mLockscreenShadeTransitionController, mCommandQueue, mInitController,
mNotificationInterruptStateProvider);
mNotificationShelfController.setOnActivatedListener(mPresenter);
@@ -1500,7 +1500,6 @@
private void inflateShelf() {
mNotificationShelfController = mSuperStatusBarViewFactory
.getNotificationShelfController(mStackScroller);
- mNotificationShelfController.setOnClickListener(mGoToLockedShadeListener);
}
@Override
@@ -1673,7 +1672,7 @@
final boolean expandEnabled = mDeviceProvisionedController.isDeviceProvisioned()
&& (mUserSetup || mUserSwitcherController == null
|| !mUserSwitcherController.isSimpleUserSwitcher())
- && ((mDisabled2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE) == 0)
+ && !isShadeDisabled()
&& ((mDisabled2 & StatusBarManager.DISABLE2_QUICK_SETTINGS) == 0)
&& !mDozing
&& !ONLY_CORE_APPS;
@@ -1681,6 +1680,10 @@
Log.d(TAG, "updateQsExpansionEnabled - QS Expand enabled: " + expandEnabled);
}
+ public boolean isShadeDisabled() {
+ return (mDisabled2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE) != 0;
+ }
+
public void addQsTile(ComponentName tile) {
if (mQSPanelController != null && mQSPanelController.getHost() != null) {
mQSPanelController.getHost().addTile(tile);
@@ -3331,7 +3334,6 @@
public void showKeyguard() {
mStatusBarStateController.setKeyguardRequested(true);
mStatusBarStateController.setLeaveOpenOnKeyguardHide(false);
- mPendingRemoteInputView = null;
updateIsKeyguard();
mAssistManagerLazy.get().onLockscreenShown();
}
@@ -3390,11 +3392,6 @@
mStatusBarStateController.setState(StatusBarState.KEYGUARD);
}
updatePanelExpansionForKeyguard();
- if (mDraggedDownEntry != null) {
- mDraggedDownEntry.setUserLocked(false);
- mDraggedDownEntry.notifyHeightChanged(false /* needsAnimation */);
- mDraggedDownEntry = null;
- }
}
private void updatePanelExpansionForKeyguard() {
@@ -3522,11 +3519,7 @@
mStatusBarStateController.setLeaveOpenOnKeyguardHide(false);
}
long delay = mKeyguardStateController.calculateGoingToFullShadeDelay();
- mNotificationPanelViewController.animateToFullShade(delay);
- if (mDraggedDownEntry != null) {
- mDraggedDownEntry.setUserLocked(false);
- mDraggedDownEntry = null;
- }
+ mLockscreenShadeTransitionController.onHideKeyguard(delay);
// Disable layout transitions in navbar for this transition because the load is just
// too heavy for the CPU and GPU on any device.
@@ -3713,7 +3706,23 @@
private void showBouncerIfKeyguard() {
if ((mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED)
&& !mKeyguardViewMediator.isHiding()) {
- mStatusBarKeyguardViewManager.showBouncer(true /* scrimmed */);
+ mStatusBarKeyguardViewManager.showGenericBouncer(true /* scrimmed */);
+ }
+ }
+
+ /**
+ * Show the bouncer if we're currently on the keyguard or shade locked and aren't hiding.
+ * @param performAction the action to perform when the bouncer is dismissed.
+ * @param cancelAction the action to perform when unlock is aborted.
+ */
+ public void showBouncerWithDimissAndCancelIfKeyguard(OnDismissAction performAction,
+ Runnable cancelAction) {
+ if ((mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED)
+ && !mKeyguardViewMediator.isHiding()) {
+ mStatusBarKeyguardViewManager.dismissWithAction(performAction, cancelAction,
+ false /* afterKeyguardGone */);
+ } else if (cancelAction != null) {
+ cancelAction.run();
}
}
@@ -3894,47 +3903,6 @@
}
/**
- * If secure with redaction: Show bouncer, go to unlocked shade.
- *
- * <p>If secure without redaction or no security: Go to {@link StatusBarState#SHADE_LOCKED}.</p>
- *
- * @param expandView The view to expand after going to the shade.
- */
- void goToLockedShade(View expandView) {
- if ((mDisabled2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE) != 0) {
- return;
- }
-
- int userId = mLockscreenUserManager.getCurrentUserId();
- ExpandableNotificationRow row = null;
- NotificationEntry entry = null;
- if (expandView instanceof ExpandableNotificationRow) {
- entry = ((ExpandableNotificationRow) expandView).getEntry();
- entry.setUserExpanded(true /* userExpanded */, true /* allowChildExpansion */);
- // Indicate that the group expansion is changing at this time -- this way the group
- // and children backgrounds / divider animations will look correct.
- entry.setGroupExpansionChanging(true);
- userId = entry.getSbn().getUserId();
- }
- boolean fullShadeNeedsBouncer = !mLockscreenUserManager.
- userAllowsPrivateNotificationsInPublic(mLockscreenUserManager.getCurrentUserId())
- || !mLockscreenUserManager.shouldShowLockscreenNotifications()
- || mFalsingCollector.shouldEnforceBouncer();
- if (mKeyguardBypassController.getBypassEnabled()) {
- fullShadeNeedsBouncer = false;
- }
- if (mLockscreenUserManager.isLockscreenPublicMode(userId) && fullShadeNeedsBouncer) {
- mStatusBarStateController.setLeaveOpenOnKeyguardHide(true);
- showBouncerIfKeyguard();
- mDraggedDownEntry = entry;
- mPendingRemoteInputView = null;
- } else {
- mNotificationPanelViewController.animateToFullShade(0 /* delay */);
- mStatusBarStateController.setState(StatusBarState.SHADE_LOCKED);
- }
- }
-
- /**
* Propagation of the bouncer state, indicating that it's fully visible.
*/
public void setBouncerShowing(boolean bouncerShowing) {
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 41bd710..91d1bd7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -365,6 +365,26 @@
return false;
}
+ /**
+ * If applicable, shows the alternate authentication bouncer. Else, shows the input
+ * (pin/password/pattern) bouncer.
+ * @param scrimmed true when the input bouncer should show scrimmed, false when the user will be
+ * dragging it and translation should be deferred {@see KeyguardBouncer#show(boolean, boolean)}
+ */
+ public void showGenericBouncer(boolean scrimmed) {
+ if (mAlternateAuthInterceptor != null) {
+ if (mAlternateAuthInterceptor.showAlternateAuthBouncer()) {
+ mStatusBar.updateScrimController();
+ }
+ return;
+ }
+
+ showBouncer(scrimmed);
+ }
+
+ /**
+ * Hides the input bouncer (pin/password/pattern).
+ */
@VisibleForTesting
void hideBouncer(boolean destroyView) {
if (mBouncer == null) {
@@ -380,7 +400,7 @@
}
/**
- * Shows the keyguard bouncer - the password challenge on the lock screen
+ * Shows the keyguard input bouncer - the password challenge on the lock screen
*
* @param scrimmed true when the bouncer should show scrimmed, false when the user will be
* dragging it and translation should be deferred {@see KeyguardBouncer#show(boolean, boolean)}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
index 2b5caf9..aa58527 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
@@ -48,6 +48,7 @@
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.KeyguardIndicationController;
+import com.android.systemui.statusbar.LockscreenShadeTransitionController;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.NotificationPresenter;
@@ -112,6 +113,7 @@
private final KeyguardIndicationController mKeyguardIndicationController;
private final StatusBar mStatusBar;
private final ShadeController mShadeController;
+ private final LockscreenShadeTransitionController mShadeTransitionController;
private final CommandQueue mCommandQueue;
private final AccessibilityManager mAccessibilityManager;
@@ -138,6 +140,7 @@
KeyguardIndicationController keyguardIndicationController,
StatusBar statusBar,
ShadeController shadeController,
+ LockscreenShadeTransitionController shadeTransitionController,
CommandQueue commandQueue,
InitController initController,
NotificationInterruptStateProvider notificationInterruptStateProvider) {
@@ -149,6 +152,7 @@
// TODO: use KeyguardStateController#isOccluded to remove this dependency
mStatusBar = statusBar;
mShadeController = shadeController;
+ mShadeTransitionController = shadeTransitionController;
mCommandQueue = commandQueue;
mAboveShelfObserver = new AboveShelfObserver(stackScrollerController.getView());
mNotificationShadeWindowController = notificationShadeWindowController;
@@ -194,6 +198,7 @@
}
};
+ mKeyguardIndicationController.init();
mViewHierarchyManager.setUpWithPresenter(this,
stackScrollerController.getNotificationListContainer());
mEntryManager.setUpWithPresenter(this);
@@ -393,7 +398,7 @@
mHeadsUpManager.setExpanded(clickedEntry, nowExpanded);
if (nowExpanded) {
if (mStatusBarStateController.getState() == StatusBarState.KEYGUARD) {
- mShadeController.goToLockedShade(clickedEntry.getRow());
+ mShadeTransitionController.goToLockedShade(clickedEntry.getRow());
} else if (clickedEntry.isSensitive()
&& mDynamicPrivacyController.isInLockedDownShade()) {
mStatusBarStateController.setLeaveOpenOnKeyguardHide(true);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
index d0d2cb2..9722d68 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
@@ -51,6 +51,7 @@
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.KeyguardIndicationController;
+import com.android.systemui.statusbar.LockscreenShadeTransitionController;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
@@ -213,6 +214,7 @@
OngoingCallController ongoingCallController,
SystemStatusAnimationScheduler animationScheduler,
StatusBarLocationPublisher locationPublisher,
+ LockscreenShadeTransitionController transitionController,
FeatureFlags featureFlags,
KeyguardUnlockAnimationController keyguardUnlockAnimationController) {
return new StatusBar(
@@ -299,6 +301,7 @@
ongoingCallController,
animationScheduler,
locationPublisher,
+ transitionController,
featureFlags,
keyguardUnlockAnimationController);
}
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 e9d256c..a019895 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
@@ -23,7 +23,7 @@
import android.app.Notification.CallStyle.CALL_TYPE_ONGOING
import android.content.Intent
import android.util.Log
-import android.view.ViewGroup
+import android.view.View
import android.widget.Chronometer
import com.android.systemui.R
import com.android.systemui.animation.ActivityLaunchAnimator
@@ -57,7 +57,7 @@
private var ongoingCallInfo: OngoingCallInfo? = null
/** True if the application managing the call is visible to the user. */
private var isCallAppVisible: Boolean = true
- private var chipView: ViewGroup? = null
+ private var chipView: View? = null
private var uidObserver: IUidObserver.Stub? = null
private val mListeners: MutableList<OngoingCallListener> = mutableListOf()
@@ -82,16 +82,14 @@
entry.sbn.notification.contentIntent.intent,
entry.sbn.uid)
updateChip()
+ } else if (isCallNotification(entry)) {
+ removeChip()
}
}
override fun onEntryRemoved(entry: NotificationEntry, reason: Int) {
if (isOngoingCallNotification(entry)) {
- ongoingCallInfo = null
- mListeners.forEach { l -> l.onOngoingCallStateChanged(animate = true) }
- if (uidObserver != null) {
- iActivityManager.unregisterUidObserver(uidObserver)
- }
+ removeChip()
}
}
}
@@ -107,7 +105,7 @@
*
* Should only be called from [CollapsedStatusBarFragment].
*/
- fun setChipView(chipView: ViewGroup) {
+ fun setChipView(chipView: View) {
this.chipView = chipView
if (hasOngoingCall()) {
updateChip()
@@ -224,6 +222,14 @@
return procState <= ActivityManager.PROCESS_STATE_TOP
}
+ private fun removeChip() {
+ ongoingCallInfo = null
+ mListeners.forEach { l -> l.onOngoingCallStateChanged(animate = true) }
+ if (uidObserver != null) {
+ iActivityManager.unregisterUidObserver(uidObserver)
+ }
+ }
+
private class OngoingCallInfo(
val callStartTime: Long,
val intent: Intent,
@@ -233,10 +239,15 @@
private fun isOngoingCallNotification(entry: NotificationEntry): Boolean {
val extras = entry.sbn.notification.extras
- val callStyleTemplateName = Notification.CallStyle::class.java.name
- return extras.getString(Notification.EXTRA_TEMPLATE) == callStyleTemplateName &&
+ return isCallNotification(entry) &&
extras.getInt(Notification.EXTRA_CALL_TYPE, -1) == CALL_TYPE_ONGOING
}
+private fun isCallNotification(entry: NotificationEntry): Boolean {
+ val extras = entry.sbn.notification.extras
+ val callStyleTemplateName = Notification.CallStyle::class.java.name
+ return extras.getString(Notification.EXTRA_TEMPLATE) == callStyleTemplateName
+}
+
private const val TAG = "OngoingCallController"
private val DEBUG = Log.isLoggable(TAG, Log.DEBUG)
diff --git a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletActivity.java b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletActivity.java
index 4cba432..83aa01f 100644
--- a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletActivity.java
@@ -16,6 +16,9 @@
package com.android.systemui.wallet.ui;
+import static android.provider.Settings.ACTION_LOCKSCREEN_SETTINGS;
+
+import android.content.Intent;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
@@ -178,7 +181,10 @@
finish();
return true;
} else if (itemId == R.id.wallet_lockscreen_settings) {
- // TODO(b/186496392): Navigate to Lock Screen Settings page when the item is clicked.
+ Intent intent =
+ new Intent(ACTION_LOCKSCREEN_SETTINGS)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ mActivityStarter.startActivity(intent, true);
return true;
}
return super.onOptionsItemSelected(item);
diff --git a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletScreenController.java b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletScreenController.java
index d9a7a8b..d0662e7 100644
--- a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletScreenController.java
+++ b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletScreenController.java
@@ -131,8 +131,14 @@
if (data.isEmpty()) {
showEmptyStateView();
} else {
- mWalletView.showCardCarousel(
- data, response.getSelectedIndex(), !mKeyguardStateController.isUnlocked());
+ int selectedIndex = response.getSelectedIndex();
+ if (selectedIndex >= data.size()) {
+ Log.w(TAG, "Invalid selected card index, showing empty state.");
+ showEmptyStateView();
+ } else {
+ mWalletView.showCardCarousel(
+ data, selectedIndex, !mKeyguardStateController.isUnlocked());
+ }
}
removeMinHeightAndRecordHeightOnLayout();
});
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
index 74077a2..92ef850 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
@@ -17,7 +17,6 @@
package com.android.systemui.wmshell;
import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BOUNCER_SHOWING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BUBBLES_EXPANDED;
@@ -35,7 +34,6 @@
import android.inputmethodservice.InputMethodService;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
-import android.view.KeyEvent;
import com.android.internal.annotations.VisibleForTesting;
import com.android.keyguard.KeyguardUpdateMonitor;
@@ -59,7 +57,6 @@
import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import com.android.wm.shell.nano.WmShellTraceProto;
import com.android.wm.shell.onehanded.OneHanded;
-import com.android.wm.shell.onehanded.OneHandedGestureHandler.OneHandedGestureEventCallback;
import com.android.wm.shell.onehanded.OneHandedTransitionCallback;
import com.android.wm.shell.onehanded.OneHandedUiEventLogger;
import com.android.wm.shell.pip.Pip;
@@ -230,10 +227,6 @@
@VisibleForTesting
void initOneHanded(OneHanded oneHanded) {
- int currentMode = mNavigationModeController.addListener(mode ->
- oneHanded.setThreeButtonModeEnabled(mode == NAV_BAR_MODE_3BUTTON));
- oneHanded.setThreeButtonModeEnabled(currentMode == NAV_BAR_MODE_3BUTTON);
-
oneHanded.registerTransitionCallback(new OneHandedTransitionCallback() {
@Override
public void onStartTransition(boolean isEntering) {
@@ -260,32 +253,6 @@
}
});
- oneHanded.registerGestureCallback(new OneHandedGestureEventCallback() {
- @Override
- public void onStart() {
- mSysUiMainExecutor.execute(() -> {
- if (oneHanded.isOneHandedEnabled()) {
- oneHanded.startOneHanded();
- } else if (oneHanded.isSwipeToNotificationEnabled()) {
- mCommandQueue.handleSystemKey(KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN);
- }
- });
- }
-
- @Override
- public void onStop() {
- mSysUiMainExecutor.execute(() -> {
- if (oneHanded.isOneHandedEnabled()) {
- // Log metrics for 3-button navigation mode.
- oneHanded.stopOneHanded(
- OneHandedUiEventLogger.EVENT_ONE_HANDED_TRIGGER_GESTURE_OUT);
- } else if (oneHanded.isSwipeToNotificationEnabled()) {
- mCommandQueue.handleSystemKey(KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP);
- }
- });
- }
- });
-
mOneHandedKeyguardCallback = new KeyguardUpdateMonitorCallback() {
@Override
public void onKeyguardBouncerChanged(boolean bouncer) {
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
index 98467d4..10322f2 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
@@ -232,6 +232,13 @@
verify(mView).removeView(mFakeSmartspaceView);
}
+ @Test
+ public void testRefresh() {
+ mController.refresh();
+
+ verify(mSmartspaceController).requestSmartspaceUpdate();
+ }
+
private void verifyAttachment(VerificationMode times) {
verify(mClockManager, times).addOnClockChangedListener(
any(ClockManager.ClockChangedListener.class));
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardHostViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardHostViewControllerTest.java
index 42314bf..6f2c565 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardHostViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardHostViewControllerTest.java
@@ -81,7 +81,7 @@
mTestableResources.addOverride(
R.bool.can_use_one_handed_bouncer, false);
mTestableResources.addOverride(
- com.android.internal.R.bool.config_enableOneHandedKeyguard, false);
+ com.android.internal.R.bool.config_enableDynamicKeyguardPositioning, false);
when(mKeyguardSecurityContainerControllerFactory.create(any(
KeyguardSecurityContainer.SecurityCallback.class)))
@@ -150,7 +150,7 @@
mTestableResources.addOverride(
R.bool.can_use_one_handed_bouncer, false);
mTestableResources.addOverride(
- com.android.internal.R.bool.config_enableOneHandedKeyguard, false);
+ com.android.internal.R.bool.config_enableDynamicKeyguardPositioning, false);
mKeyguardHostViewController.init();
assertEquals(
@@ -161,7 +161,7 @@
mTestableResources.addOverride(
R.bool.can_use_one_handed_bouncer, true);
mTestableResources.addOverride(
- com.android.internal.R.bool.config_enableOneHandedKeyguard, true);
+ com.android.internal.R.bool.config_enableDynamicKeyguardPositioning, true);
mKeyguardHostViewController.updateResources();
assertEquals(
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
index 9557d5c..f5916e7 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
@@ -246,7 +246,8 @@
boolean sysuiResourceCanUseOneHandedKeyguard,
SecurityMode securityMode) {
TestableResources testableResources = mContext.getOrCreateTestableResources();
- testableResources.addOverride(com.android.internal.R.bool.config_enableOneHandedKeyguard,
+ testableResources.addOverride(
+ com.android.internal.R.bool.config_enableDynamicKeyguardPositioning,
deviceConfigCanUseOneHandedKeyguard);
testableResources.addOverride(R.bool.can_use_one_handed_bouncer,
sysuiResourceCanUseOneHandedKeyguard);
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index f779305..29b4405 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -943,6 +943,34 @@
}
@Test
+ public void testShouldNotUpdateBiometricListeningStateOnStatusBarStateChange() {
+ // GIVEN state for face auth should run aside from StatusBarState
+ when(mDevicePolicyManager.getKeyguardDisabledFeatures(null,
+ KeyguardUpdateMonitor.getCurrentUser())).thenReturn(0);
+ mStatusBarStateListener.onStateChanged(StatusBarState.SHADE_LOCKED);
+ setKeyguardBouncerVisibility(false /* isVisible */);
+ mKeyguardUpdateMonitor.dispatchStartedWakingUp();
+ when(mKeyguardBypassController.canBypass()).thenReturn(true);
+ mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(true);
+
+ // WHEN status bar state reports a change to the keyguard that would normally indicate to
+ // start running face auth
+ mStatusBarStateListener.onStateChanged(StatusBarState.KEYGUARD);
+ assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isEqualTo(true);
+
+ // THEN face unlock is not running b/c status bar state changes don't cause biometric
+ // listening state to update
+ assertThat(mKeyguardUpdateMonitor.isFaceUnlockRunning(
+ KeyguardUpdateMonitor.getCurrentUser())).isEqualTo(false);
+
+ // WHEN biometric listening state is updated
+ mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(true);
+
+ // THEN face unlock is running
+ assertThat(mKeyguardUpdateMonitor.isFaceDetectionRunning()).isEqualTo(true);
+ }
+
+ @Test
public void testRequireUnlockForNfc_Broadcast() {
KeyguardUpdateMonitorCallback callback = mock(KeyguardUpdateMonitorCallback.class);
mKeyguardUpdateMonitor.registerCallback(callback);
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 3d504fb..d9a240f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java
@@ -22,6 +22,7 @@
import static android.view.MotionEvent.ACTION_DOWN;
import static android.view.MotionEvent.ACTION_MOVE;
import static android.view.MotionEvent.ACTION_UP;
+import static android.view.WindowInsets.Type.systemBars;
import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK;
import static com.android.systemui.accessibility.MagnificationModeSwitch.DEFAULT_FADE_OUT_ANIMATION_DELAY_MS;
@@ -33,6 +34,7 @@
import static org.hamcrest.CoreMatchers.hasItems;
import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -41,19 +43,27 @@
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.pm.ActivityInfo;
+import android.graphics.Insets;
+import android.graphics.Rect;
+import android.os.Handler;
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.view.Choreographer;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewPropertyAnimator;
+import android.view.WindowInsets;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
@@ -61,6 +71,7 @@
import androidx.test.filters.SmallTest;
+import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
@@ -69,6 +80,7 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
+import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
@@ -77,6 +89,7 @@
@SmallTest
@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
public class MagnificationModeSwitchTest extends SysuiTestCase {
private static final float FADE_IN_ALPHA = 1f;
@@ -86,7 +99,10 @@
@Mock
private AccessibilityManager mAccessibilityManager;
@Mock
- private WindowManager mWindowManager;
+ private SfVsyncFrameCallbackProvider mSfVsyncFrameProvider;
+ @Mock
+ private Handler mHandler;
+ private TestableWindowManager mWindowManager;
private ViewPropertyAnimator mViewPropertyAnimator;
private MagnificationModeSwitch mMagnificationModeSwitch;
private View.OnTouchListener mTouchListener;
@@ -96,10 +112,8 @@
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
- WindowManager wm = mContext.getSystemService(WindowManager.class);
- doAnswer(invocation ->
- wm.getMaximumWindowMetrics()
- ).when(mWindowManager).getMaximumWindowMetrics();
+ final WindowManager wm = mContext.getSystemService(WindowManager.class);
+ mWindowManager = spy(new TestableWindowManager(wm));
mContext.addMockSystemService(Context.WINDOW_SERVICE, mWindowManager);
mContext.addMockSystemService(Context.ACCESSIBILITY_SERVICE, mAccessibilityManager);
mSpyImageView = Mockito.spy(new ImageView(mContext));
@@ -110,7 +124,14 @@
return null;
}).when(mSpyImageView).setOnTouchListener(
any(View.OnTouchListener.class));
- mMagnificationModeSwitch = new MagnificationModeSwitch(mContext, mSpyImageView);
+ doAnswer(invocation -> {
+ Choreographer.FrameCallback callback = invocation.getArgument(0);
+ callback.doFrame(0);
+ return null;
+ }).when(mSfVsyncFrameProvider).postFrameCallback(
+ any(Choreographer.FrameCallback.class));
+ mMagnificationModeSwitch = new MagnificationModeSwitch(mContext, mSpyImageView,
+ mSfVsyncFrameProvider);
assertNotNull(mTouchListener);
}
@@ -178,20 +199,65 @@
}
@Test
- public void onConfigurationChanged_buttonIsShowing_updateResourcesAndLayout() {
+ public void onDensityChanged_buttonIsShowing_updateResourcesAndLayout() {
mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
resetAndStubMockImageViewAndAnimator();
mMagnificationModeSwitch.onConfigurationChanged(ActivityInfo.CONFIG_DENSITY);
- verify(mSpyImageView).setPadding(anyInt(), anyInt(), anyInt(), anyInt());
- verify(mSpyImageView).setImageResource(
- getIconResId(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN));
- verify(mWindowManager).updateViewLayout(eq(mSpyImageView), any());
+ InOrder inOrder = Mockito.inOrder(mWindowManager);
+ inOrder.verify(mWindowManager).updateViewLayout(eq(mSpyImageView), any());
+ inOrder.verify(mWindowManager).removeView(eq(mSpyImageView));
+ inOrder.verify(mWindowManager).addView(eq(mSpyImageView), any());
verify(mSpyImageView).setSystemGestureExclusionRects(any(List.class));
}
@Test
+ public void onApplyWindowInsetsWithBoundsChange_buttonIsShowing_updateLayoutPosition() {
+ mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
+
+ mMagnificationModeSwitch.mDraggableWindowBounds.inset(10, 10);
+ mSpyImageView.onApplyWindowInsets(WindowInsets.CONSUMED);
+
+ verify(mWindowManager).updateViewLayout(eq(mSpyImageView),
+ any(WindowManager.LayoutParams.class));
+ assertLayoutPosition(/* toLeftScreenEdge= */ false);
+ }
+
+ @Test
+ public void onApplyWindowInsetsWithWindowInsetsChange_buttonIsShowing_draggableBoundsChanged() {
+ mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
+ final Rect oldDraggableBounds = new Rect(mMagnificationModeSwitch.mDraggableWindowBounds);
+
+ mWindowManager.setWindowInsets(new WindowInsets.Builder()
+ .setInsetsIgnoringVisibility(systemBars(), Insets.of(0, 20, 0, 20))
+ .build());
+ mSpyImageView.onApplyWindowInsets(WindowInsets.CONSUMED);
+
+ assertNotEquals(oldDraggableBounds, mMagnificationModeSwitch.mDraggableWindowBounds);
+ }
+
+ @Test
+ public void onDraggingGestureFinish_buttonIsShowing_stickToRightEdge() {
+ final int windowHalfWidth =
+ mWindowManager.getCurrentWindowMetrics().getBounds().width() / 2;
+ mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
+
+ // Drag button to right side on screen
+ final int offset = ViewConfiguration.get(mContext).getScaledTouchSlop() + 10;
+ final long downTime = SystemClock.uptimeMillis();
+ mTouchListener.onTouch(mSpyImageView, obtainMotionEvent(
+ downTime, 0, ACTION_DOWN, 100, 100));
+ mTouchListener.onTouch(mSpyImageView,
+ obtainMotionEvent(downTime, downTime, ACTION_MOVE, windowHalfWidth - offset, 100));
+
+ mTouchListener.onTouch(mSpyImageView, obtainMotionEvent(
+ downTime, downTime, ACTION_UP, windowHalfWidth - offset, 100));
+
+ assertLayoutPosition(/* toLeftScreenEdge= */false);
+ }
+
+ @Test
public void performSingleTap_fullscreenMode_removeViewAndChangeSettingsValue() {
mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
resetAndStubMockImageViewAndAnimator();
@@ -344,12 +410,12 @@
public void showButton_hasAccessibilityWindowTitle() {
mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
- ArgumentCaptor<WindowManager.LayoutParams> paramsArgumentCaptor = ArgumentCaptor.forClass(
- WindowManager.LayoutParams.class);
- verify(mWindowManager).addView(eq(mSpyImageView), paramsArgumentCaptor.capture());
+ final WindowManager.LayoutParams layoutPrams =
+ mWindowManager.getLayoutParamsFromAttachedView();
+ assertNotNull(layoutPrams);
assertEquals(getContext().getResources().getString(
com.android.internal.R.string.android_system_label),
- paramsArgumentCaptor.getValue().accessibilityTitle);
+ layoutPrams.accessibilityTitle);
}
@Test
@@ -361,10 +427,10 @@
com.android.internal.R.string.android_system_label, newA11yWindowTitle);
mMagnificationModeSwitch.onConfigurationChanged(ActivityInfo.CONFIG_LOCALE);
- ArgumentCaptor<WindowManager.LayoutParams> paramsArgumentCaptor = ArgumentCaptor.forClass(
- WindowManager.LayoutParams.class);
- verify(mWindowManager).updateViewLayout(eq(mSpyImageView), paramsArgumentCaptor.capture());
- assertEquals(newA11yWindowTitle, paramsArgumentCaptor.getValue().accessibilityTitle);
+ final WindowManager.LayoutParams layoutParams =
+ mWindowManager.getLayoutParamsFromAttachedView();
+ assertNotNull(layoutParams);
+ assertEquals(newA11yWindowTitle, layoutParams.accessibilityTitle);
}
private void assertModeUnchanged(int expectedMode) {
@@ -374,7 +440,7 @@
}
private void assertShowFadingAnimation(float alpha) {
- ArgumentCaptor<Runnable> runnableCaptor = ArgumentCaptor.forClass(Runnable.class);
+ final ArgumentCaptor<Runnable> runnableCaptor = ArgumentCaptor.forClass(Runnable.class);
if (alpha == FADE_IN_ALPHA) { // Fade-in
verify(mSpyImageView).postOnAnimation(runnableCaptor.capture());
} else { // Fade-out
@@ -392,6 +458,13 @@
private void resetAndStubMockImageViewAndAnimator() {
resetAndStubMockAnimator();
Mockito.reset(mSpyImageView);
+ final Handler handler = mock(Handler.class);
+ when(mSpyImageView.getHandler()).thenReturn(handler);
+ doAnswer(invocation -> {
+ final Runnable runnable = invocation.getArgument(0);
+ runnable.run();
+ return null;
+ }).when(handler).post(any(Runnable.class));
doAnswer(invocation -> {
final Runnable runnable = invocation.getArgument(0);
runnable.run();
@@ -440,4 +513,16 @@
mFadeOutAnimation.run();
mFadeOutAnimation = null;
}
+
+ private void assertLayoutPosition(boolean toLeftScreenEdge) {
+ final int expectedX =
+ toLeftScreenEdge ? mMagnificationModeSwitch.mDraggableWindowBounds.left
+ : mMagnificationModeSwitch.mDraggableWindowBounds.right;
+ final int expectedY = mMagnificationModeSwitch.mDraggableWindowBounds.bottom;
+ final WindowManager.LayoutParams layoutParams =
+ mWindowManager.getLayoutParamsFromAttachedView();
+ assertNotNull(layoutParams);
+ assertEquals(expectedX, layoutParams.x);
+ assertEquals(expectedY, layoutParams.y);
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/TestableWindowManager.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/TestableWindowManager.java
new file mode 100644
index 0000000..4f095ac
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/TestableWindowManager.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.accessibility;
+
+import static android.view.WindowInsets.Type.systemGestures;
+
+import android.graphics.Insets;
+import android.graphics.Region;
+import android.view.Display;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowInsets;
+import android.view.WindowManager;
+import android.view.WindowMetrics;
+
+public class TestableWindowManager implements WindowManager {
+
+ private final WindowManager mWindowManager;
+ private View mView;
+ private WindowInsets mWindowInsets = null;
+
+ TestableWindowManager(WindowManager windowManager) {
+ mWindowManager = windowManager;
+ }
+
+ @Override
+ public Display getDefaultDisplay() {
+ return mWindowManager.getDefaultDisplay();
+ }
+
+ @Override
+ public void removeViewImmediate(View view) {
+ mWindowManager.removeViewImmediate(view);
+ }
+
+ @Override
+ public void requestAppKeyboardShortcuts(WindowManager.KeyboardShortcutsReceiver receiver,
+ int deviceId) {
+ mWindowManager.requestAppKeyboardShortcuts(receiver, deviceId);
+ }
+
+ @Override
+ public Region getCurrentImeTouchRegion() {
+ return mWindowManager.getCurrentImeTouchRegion();
+ }
+
+ @Override
+ public void addView(View view, ViewGroup.LayoutParams params) {
+ mView = view;
+ mWindowManager.addView(view, params);
+ }
+
+ @Override
+ public void updateViewLayout(View view, ViewGroup.LayoutParams params) {
+ mWindowManager.updateViewLayout(view, params);
+ }
+
+ @Override
+ public void removeView(View view) {
+ mView = null;
+ mWindowManager.removeView(view);
+ }
+
+ @Override
+ public WindowMetrics getCurrentWindowMetrics() {
+ final Insets systemGesturesInsets = Insets.of(0, 0, 0, 10);
+ final WindowInsets insets = new WindowInsets.Builder()
+ .setInsets(systemGestures(), systemGesturesInsets)
+ .build();
+ final WindowMetrics windowMetrics = new WindowMetrics(
+ mWindowManager.getCurrentWindowMetrics().getBounds(),
+ mWindowInsets == null ? insets : mWindowInsets);
+ return windowMetrics;
+ }
+
+ @Override
+ public WindowMetrics getMaximumWindowMetrics() {
+ return mWindowManager.getMaximumWindowMetrics();
+ }
+
+ public View getAttachedView() {
+ return mView;
+ }
+
+ public WindowManager.LayoutParams getLayoutParamsFromAttachedView() {
+ if (mView == null) {
+ return null;
+ }
+ return (WindowManager.LayoutParams) mView.getLayoutParams();
+ }
+
+ public void setWindowInsets(WindowInsets insets) {
+ mWindowInsets = insets;
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
index b8734df..5fa63bc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
@@ -17,7 +17,6 @@
package com.android.systemui.accessibility;
import static android.view.Choreographer.FrameCallback;
-import static android.view.WindowInsets.Type.systemGestures;
import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_MAGNIFICATION_OVERLAP;
@@ -46,9 +45,7 @@
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.res.Resources;
-import android.graphics.Insets;
import android.graphics.Rect;
-import android.graphics.Region;
import android.os.Handler;
import android.os.SystemClock;
import android.testing.AndroidTestingRunner;
@@ -58,10 +55,7 @@
import android.view.Surface;
import android.view.SurfaceControl;
import android.view.View;
-import android.view.ViewGroup;
-import android.view.WindowInsets;
import android.view.WindowManager;
-import android.view.WindowMetrics;
import android.view.accessibility.AccessibilityNodeInfo;
import androidx.test.InstrumentationRegistry;
@@ -96,14 +90,13 @@
private MirrorWindowControl mMirrorWindowControl;
@Mock
private WindowMagnifierCallback mWindowMagnifierCallback;
- @Mock (answer = Answers.RETURNS_DEEP_STUBS)
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
private SurfaceControl.Transaction mTransaction;
- private WindowManager mWindowManager;
+ private TestableWindowManager mWindowManager;
private SysUiState mSysUiState = new SysUiState();
private Resources mResources;
private WindowMagnificationController mWindowMagnificationController;
private Instrumentation mInstrumentation;
- private View mMirrorView;
@Before
public void setUp() {
@@ -157,7 +150,9 @@
timeout(LAYOUT_CHANGE_TIMEOUT_MS)).onWindowMagnifierBoundsChanged(
eq(mContext.getDisplayId()), boundsCaptor.capture());
final Rect actualBounds = new Rect();
- mMirrorView.getBoundsOnScreen(actualBounds);
+ final View mirrorView = mWindowManager.getAttachedView();
+ assertNotNull(mirrorView);
+ mirrorView.getBoundsOnScreen(actualBounds);
assertEquals(actualBounds, boundsCaptor.getValue());
}
@@ -218,7 +213,9 @@
ArgumentCaptor<Runnable> runnableArgumentCaptor = ArgumentCaptor.forClass(Runnable.class);
verify(mHandler).postDelayed(runnableArgumentCaptor.capture(), anyLong());
runnableArgumentCaptor.getValue().run();
- assertThat(mMirrorView.getStateDescription().toString(), containsString("300"));
+ final View mirrorView = mWindowManager.getAttachedView();
+ assertNotNull(mirrorView);
+ assertThat(mirrorView.getStateDescription().toString(), containsString("300"));
}
@Test
@@ -300,10 +297,11 @@
mWindowMagnificationController.enableWindowMagnification(2.5f, Float.NaN,
Float.NaN);
});
- assertNotNull(mMirrorView);
+ final View mirrorView = mWindowManager.getAttachedView();
+ assertNotNull(mirrorView);
final AccessibilityNodeInfo nodeInfo = new AccessibilityNodeInfo();
- mMirrorView.onInitializeAccessibilityNodeInfo(nodeInfo);
+ mirrorView.onInitializeAccessibilityNodeInfo(nodeInfo);
assertNotNull(nodeInfo.getContentDescription());
assertThat(nodeInfo.getStateDescription().toString(), containsString("250"));
@@ -323,24 +321,24 @@
mWindowMagnificationController.enableWindowMagnification(2.5f, Float.NaN,
Float.NaN);
});
- assertNotNull(mMirrorView);
+ final View mirrorView = mWindowManager.getAttachedView();
assertTrue(
- mMirrorView.performAccessibilityAction(R.id.accessibility_action_zoom_out, null));
+ mirrorView.performAccessibilityAction(R.id.accessibility_action_zoom_out, null));
// Minimum scale is 2.0.
verify(mWindowMagnifierCallback).onPerformScaleAction(eq(displayId), eq(2.0f));
- assertTrue(mMirrorView.performAccessibilityAction(R.id.accessibility_action_zoom_in, null));
+ assertTrue(mirrorView.performAccessibilityAction(R.id.accessibility_action_zoom_in, null));
verify(mWindowMagnifierCallback).onPerformScaleAction(eq(displayId), eq(3.5f));
// TODO: Verify the final state when the mirror surface is visible.
- assertTrue(mMirrorView.performAccessibilityAction(R.id.accessibility_action_move_up, null));
+ assertTrue(mirrorView.performAccessibilityAction(R.id.accessibility_action_move_up, null));
assertTrue(
- mMirrorView.performAccessibilityAction(R.id.accessibility_action_move_down, null));
+ mirrorView.performAccessibilityAction(R.id.accessibility_action_move_down, null));
assertTrue(
- mMirrorView.performAccessibilityAction(R.id.accessibility_action_move_right, null));
+ mirrorView.performAccessibilityAction(R.id.accessibility_action_move_right, null));
assertTrue(
- mMirrorView.performAccessibilityAction(R.id.accessibility_action_move_left, null));
+ mirrorView.performAccessibilityAction(R.id.accessibility_action_move_left, null));
}
@Test
@@ -351,7 +349,8 @@
Float.NaN);
});
- mMirrorView.performAccessibilityAction(R.id.accessibility_action_move_up, null);
+ final View mirrorView = mWindowManager.getAttachedView();
+ mirrorView.performAccessibilityAction(R.id.accessibility_action_move_up, null);
verify(mWindowMagnifierCallback).onAccessibilityActionPerformed(eq(displayId));
}
@@ -363,12 +362,8 @@
Float.NaN);
});
- ArgumentCaptor<WindowManager.LayoutParams> paramsArgumentCaptor = ArgumentCaptor.forClass(
- WindowManager.LayoutParams.class);
- verify(mWindowManager).addView(eq(mMirrorView), paramsArgumentCaptor.capture());
assertEquals(getContext().getResources().getString(
- com.android.internal.R.string.android_system_label),
- paramsArgumentCaptor.getValue().accessibilityTitle);
+ com.android.internal.R.string.android_system_label), getAccessibilityWindowTitle());
}
@Test
@@ -400,15 +395,15 @@
mWindowMagnificationController.onSingleTap();
});
+ final View mirrorView = mWindowManager.getAttachedView();
final long timeout = SystemClock.uptimeMillis() + 1000;
while (SystemClock.uptimeMillis() < timeout) {
SystemClock.sleep(10);
-
- if (Float.compare(1.0f, mMirrorView.getScaleX()) < 0) {
+ if (Float.compare(1.0f, mirrorView.getScaleX()) < 0) {
return;
}
}
- fail("mMirrorView scale is not changed");
+ fail("MirrorView scale is not changed");
}
@Test
@@ -428,77 +423,16 @@
}
private CharSequence getAccessibilityWindowTitle() {
- if (mMirrorView == null) {
- return null;
+ final View mirrorView = mWindowManager.getAttachedView();
+ if (mirrorView == null) {
+ return null;
}
WindowManager.LayoutParams layoutParams =
- (WindowManager.LayoutParams) mMirrorView.getLayoutParams();
+ (WindowManager.LayoutParams) mirrorView.getLayoutParams();
return layoutParams.accessibilityTitle;
}
private boolean hasMagnificationOverlapFlag() {
return (mSysUiState.getFlags() & SYSUI_STATE_MAGNIFICATION_OVERLAP) != 0;
}
-
- private class TestableWindowManager implements WindowManager {
-
- private final WindowManager mWindowManager;
-
- TestableWindowManager(WindowManager windowManager) {
- mWindowManager = windowManager;
- }
-
- @Override
- public Display getDefaultDisplay() {
- return mWindowManager.getDefaultDisplay();
- }
-
- @Override
- public void removeViewImmediate(View view) {
- mWindowManager.removeViewImmediate(view);
- }
-
- @Override
- public void requestAppKeyboardShortcuts(KeyboardShortcutsReceiver receiver, int deviceId) {
- mWindowManager.requestAppKeyboardShortcuts(receiver, deviceId);
- }
-
- @Override
- public Region getCurrentImeTouchRegion() {
- return mWindowManager.getCurrentImeTouchRegion();
- }
-
- @Override
- public void addView(View view, ViewGroup.LayoutParams params) {
- mMirrorView = view;
- mWindowManager.addView(view, params);
- }
-
- @Override
- public void updateViewLayout(View view, ViewGroup.LayoutParams params) {
- mWindowManager.updateViewLayout(view, params);
- }
-
- @Override
- public void removeView(View view) {
- mMirrorView = null;
- mWindowManager.removeView(view);
- }
-
- @Override
- public WindowMetrics getCurrentWindowMetrics() {
- final Insets systemGesturesInsets = Insets.of(0, 0, 0, 10);
- final WindowInsets insets = new WindowInsets.Builder()
- .setInsets(systemGestures(), systemGesturesInsets)
- .build();
- final WindowMetrics windowMetrics = new WindowMetrics(
- mWindowManager.getCurrentWindowMetrics().getBounds(), insets);
- return windowMetrics;
- }
-
- @Override
- public WindowMetrics getMaximumWindowMetrics() {
- return mWindowManager.getMaximumWindowMetrics();
- }
- }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingCollectorImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingCollectorImplTest.java
index bc24445..3c41216 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingCollectorImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingCollectorImplTest.java
@@ -21,6 +21,7 @@
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -185,7 +186,7 @@
}
@Test
- public void testAvoidDozing() {
+ public void testAvoidDozingNotPulsing() {
MotionEvent down = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 0, 0);
MotionEvent up = MotionEvent.obtain(0, 0, MotionEvent.ACTION_UP, 0, 0, 0);
@@ -199,4 +200,21 @@
mFalsingCollector.onTouchEvent(up);
verify(mFalsingDataProvider, never()).onMotionEvent(any(MotionEvent.class));
}
+
+ @Test
+ public void testAvoidDozingButPulsing() {
+ MotionEvent down = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 0, 0);
+ MotionEvent up = MotionEvent.obtain(0, 0, MotionEvent.ACTION_UP, 0, 0, 0);
+
+ when(mStatusBarStateController.isDozing()).thenReturn(true);
+ when(mStatusBarStateController.isPulsing()).thenReturn(true);
+
+ // Nothing passed initially
+ mFalsingCollector.onTouchEvent(down);
+ verify(mFalsingDataProvider, never()).onMotionEvent(any(MotionEvent.class));
+
+ // Up event would flushes
+ mFalsingCollector.onTouchEvent(up);
+ verify(mFalsingDataProvider, times(2)).onMotionEvent(any(MotionEvent.class));
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/dagger/ControlsComponentTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/dagger/ControlsComponentTest.kt
index c678f46..ecefb55 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/dagger/ControlsComponentTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/dagger/ControlsComponentTest.kt
@@ -115,7 +115,7 @@
`when`(lockPatternUtils.getStrongAuthForUser(anyInt()))
.thenReturn(STRONG_AUTH_NOT_REQUIRED)
`when`(keyguardStateController.isUnlocked()).thenReturn(false)
- `when`(secureSettings.getInt(eq(Settings.Secure.POWER_MENU_LOCKED_SHOW_CONTENT), anyInt()))
+ `when`(secureSettings.getInt(eq(Settings.Secure.LOCKSCREEN_SHOW_CONTROLS), anyInt()))
.thenReturn(0)
val component = setupComponent(true)
@@ -127,7 +127,7 @@
`when`(lockPatternUtils.getStrongAuthForUser(anyInt()))
.thenReturn(STRONG_AUTH_NOT_REQUIRED)
`when`(keyguardStateController.isUnlocked()).thenReturn(false)
- `when`(secureSettings.getInt(eq(Settings.Secure.POWER_MENU_LOCKED_SHOW_CONTENT), anyInt()))
+ `when`(secureSettings.getInt(eq(Settings.Secure.LOCKSCREEN_SHOW_CONTROLS), anyInt()))
.thenReturn(1)
val component = setupComponent(true)
@@ -136,7 +136,7 @@
@Test
fun testFeatureEnabledAndCanShowWhileUnlockedVisibility() {
- `when`(secureSettings.getInt(eq(Settings.Secure.POWER_MENU_LOCKED_SHOW_CONTENT), anyInt()))
+ `when`(secureSettings.getInt(eq(Settings.Secure.LOCKSCREEN_SHOW_CONTROLS), anyInt()))
.thenReturn(0)
`when`(lockPatternUtils.getStrongAuthForUser(anyInt()))
.thenReturn(STRONG_AUTH_NOT_REQUIRED)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlViewHolderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlViewHolderTest.kt
new file mode 100644
index 0000000..47ab17d
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlViewHolderTest.kt
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.controls.ui
+
+import android.app.PendingIntent
+import android.content.ComponentName
+import android.content.res.ColorStateList
+import android.graphics.drawable.GradientDrawable
+import android.graphics.drawable.Icon
+import android.service.controls.Control
+import android.service.controls.DeviceTypes
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.test.filters.SmallTest
+import com.android.systemui.R
+import com.android.systemui.controls.controller.ControlsController
+import com.android.systemui.util.time.FakeSystemClock
+import org.junit.runner.RunWith
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.controls.ControlsMetricsLogger
+import com.android.systemui.controls.controller.ControlInfo
+import com.android.systemui.util.concurrency.FakeExecutor
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.mockito.Mockito.mock
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@TestableLooper.RunWithLooper
+class ControlViewHolderTest : SysuiTestCase() {
+
+ private val clock = FakeSystemClock()
+
+ private lateinit var cvh: ControlViewHolder
+
+ @Before
+ fun setUp() {
+ TestableLooper.get(this).runWithLooper {
+ val baseLayout = LayoutInflater.from(mContext).inflate(
+ R.layout.controls_base_item, null, false) as ViewGroup
+
+ cvh = ControlViewHolder(
+ baseLayout,
+ mock(ControlsController::class.java),
+ FakeExecutor(clock),
+ FakeExecutor(clock),
+ mock(ControlActionCoordinator::class.java),
+ mock(ControlsMetricsLogger::class.java),
+ uid = 100
+ )
+
+ val cws = ControlWithState(
+ ComponentName.createRelative("pkg", "cls"),
+ ControlInfo(
+ CONTROL_ID, CONTROL_TITLE, "subtitle", DeviceTypes.TYPE_AIR_FRESHENER
+ ),
+ Control.StatelessBuilder(CONTROL_ID, mock(PendingIntent::class.java)).build()
+ )
+
+ cvh.bindData(cws, isLocked = false)
+ }
+ }
+
+ @Test
+ fun updateStatusRow_customIconWithTint_iconTintRemains() {
+ val control = Control.StatelessBuilder(DEFAULT_CONTROL)
+ .setCustomIcon(
+ Icon.createWithResource(mContext.resources, R.drawable.ic_emergency_star)
+ .setTint(TINT_COLOR)
+ )
+ .build()
+
+ cvh.updateStatusRow(enabled = true, CONTROL_TITLE, DRAWABLE, COLOR, control)
+
+ assertThat(cvh.icon.imageTintList).isEqualTo(ColorStateList.valueOf(TINT_COLOR))
+ }
+
+ @Test
+ fun updateStatusRow_customIconWithTintList_iconTintListRemains() {
+ val customIconTintList = ColorStateList.valueOf(TINT_COLOR)
+ val control = Control.StatelessBuilder(CONTROL_ID, mock(PendingIntent::class.java))
+ .setCustomIcon(
+ Icon.createWithResource(mContext.resources, R.drawable.ic_emergency_star)
+ .setTintList(customIconTintList)
+ )
+ .build()
+
+ cvh.updateStatusRow(enabled = true, CONTROL_TITLE, DRAWABLE, COLOR, control)
+
+ assertThat(cvh.icon.imageTintList).isEqualTo(customIconTintList)
+ }
+}
+
+private const val CONTROL_ID = "CONTROL_ID"
+private const val CONTROL_TITLE = "CONTROL_TITLE"
+private const val TINT_COLOR = 0x00ff00 // Should be different from [COLOR]
+
+private val DRAWABLE = GradientDrawable()
+private val COLOR = ColorStateList.valueOf(0xffff00)
+private val DEFAULT_CONTROL = Control.StatelessBuilder(
+ CONTROL_ID, mock(PendingIntent::class.java)).build()
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataFilterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataFilterTest.kt
index bfd60b96..fc0506a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataFilterTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataFilterTest.kt
@@ -30,6 +30,7 @@
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.anyBoolean
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Mock
import org.mockito.Mockito
@@ -228,37 +229,39 @@
}
@Test
- fun testOnSmartspaceMediaDataLoaded_noMedia_nonEmptyRecommendation_usesSmartspace() {
+ fun testOnSmartspaceMediaDataLoaded_noMedia_nonEmptyRec_prioritizesSmartspace() {
mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
- verify(listener).onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData))
+ verify(listener)
+ .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(true))
assertThat(mediaDataFilter.hasActiveMedia()).isTrue()
}
@Test
- fun testOnSmartspaceMediaDataLoaded_noMedia_emptyRecommendation_showsNothing() {
+ fun testOnSmartspaceMediaDataLoaded_noMedia_emptyRec_showsNothing() {
`when`(smartspaceData.iconGrid).thenReturn(listOf())
mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
verify(listener, never())
- .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData))
+ .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), anyBoolean())
assertThat(mediaDataFilter.hasActiveMedia()).isTrue()
}
@Test
- fun testOnSmartspaceMediaDataLoaded_noRecentMedia_nonEmptyRecommendation_usesSmartspace() {
+ fun testOnSmartspaceMediaDataLoaded_noRecentMedia_nonEmptyRec_prioritizesSmartspace() {
val dataOld = dataMain.copy(active = false, lastActive = clock.elapsedRealtime())
mediaDataFilter.onMediaDataLoaded(KEY, null, dataOld)
clock.advanceTime(SMARTSPACE_MAX_AGE + 100)
mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
- verify(listener).onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData))
+ verify(listener)
+ .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(true))
assertThat(mediaDataFilter.hasActiveMedia()).isTrue()
}
@Test
- fun testOnSmartspaceMediaDataLoaded_noRecentMedia_emptyRecommendation_showsNothing() {
+ fun testOnSmartspaceMediaDataLoaded_noRecentMedia_emptyRec_showsNothing() {
`when`(smartspaceData.iconGrid).thenReturn(listOf())
val dataOld = dataMain.copy(active = false, lastActive = clock.elapsedRealtime())
@@ -267,12 +270,14 @@
mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
verify(listener, never())
- .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData))
+ .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), anyBoolean())
assertThat(mediaDataFilter.hasActiveMedia()).isTrue()
}
@Test
- fun testOnSmartspaceMediaDataLoaded_hasRecentMedia_usesMedia() {
+ fun testOnSmartspaceMediaDataLoaded_hasRecentMedia_emptyRec_usesMedia() {
+ `when`(smartspaceData.iconGrid).thenReturn(listOf())
+
// WHEN we have media that was recently played, but not currently active
val dataCurrent = dataMain.copy(active = false, lastActive = clock.elapsedRealtime())
mediaDataFilter.onMediaDataLoaded(KEY, null, dataCurrent)
@@ -285,19 +290,41 @@
val dataCurrentAndActive = dataCurrent.copy(active = true)
verify(listener).onMediaDataLoaded(eq(KEY), eq(KEY), eq(dataCurrentAndActive))
assertThat(mediaDataFilter.hasActiveMedia()).isTrue()
+ // Smartspace update shouldn't be propagated for the empty rec list.
+ verify(listener, never())
+ .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), anyBoolean())
}
@Test
- fun testOnSmartspaceMediaDataRemoved_usedSmartspace_clearsMedia() {
+ fun testOnSmartspaceMediaDataLoaded_hasRecentMedia_nonEmptyRec_usesBoth() {
+ // WHEN we have media that was recently played, but not currently active
+ val dataCurrent = dataMain.copy(active = false, lastActive = clock.elapsedRealtime())
+ mediaDataFilter.onMediaDataLoaded(KEY, null, dataCurrent)
+ verify(listener).onMediaDataLoaded(eq(KEY), eq(null), eq(dataCurrent))
+
+ // AND we get a smartspace signal
+ mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
+
+ // THEN we should tell listeners to treat the media as active instead
+ val dataCurrentAndActive = dataCurrent.copy(active = true)
+ verify(listener).onMediaDataLoaded(eq(KEY), eq(KEY), eq(dataCurrentAndActive))
+ assertThat(mediaDataFilter.hasActiveMedia()).isTrue()
+ // Smartspace update should also be propagated but not prioritized.
+ verify(listener)
+ .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(false))
+ }
+
+ @Test
+ fun testOnSmartspaceMediaDataRemoved_usedSmartspace_clearsSmartspace() {
mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
mediaDataFilter.onSmartspaceMediaDataRemoved(SMARTSPACE_KEY)
verify(listener).onSmartspaceMediaDataRemoved(SMARTSPACE_KEY)
- assertThat(mediaDataFilter.hasActiveMedia()).isFalse()
+ assertThat(mediaDataFilter.hasSmartspace).isFalse()
}
@Test
- fun testOnSmartspaceMediaDataRemoved_usedMedia_clearsMedia() {
+ fun testOnSmartspaceMediaDataRemoved_usedMediaAndSmartspace_clearsBoth() {
val dataCurrent = dataMain.copy(active = false, lastActive = clock.elapsedRealtime())
mediaDataFilter.onMediaDataLoaded(KEY, null, dataCurrent)
mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
@@ -305,6 +332,8 @@
mediaDataFilter.onSmartspaceMediaDataRemoved(SMARTSPACE_KEY)
verify(listener).onMediaDataLoaded(eq(KEY), eq(KEY), eq(dataCurrent))
+ verify(listener).onSmartspaceMediaDataRemoved(SMARTSPACE_KEY)
assertThat(mediaDataFilter.hasActiveMedia()).isFalse()
+ assertThat(mediaDataFilter.hasSmartspace).isFalse()
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt
index acfc513..59527f6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt
@@ -28,6 +28,7 @@
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
+import org.mockito.ArgumentMatchers.anyBoolean
import org.mockito.Captor
import org.mockito.Mock
import org.mockito.Mockito
@@ -41,7 +42,6 @@
private const val KEY = "KEY"
private const val KEY_2 = "KEY_2"
private const val KEY_MEDIA_SMARTSPACE = "MEDIA_SMARTSPACE_ID"
-private const val KEY_NONE_MEDIA_SMARTSPACE = "NONE_MEDIA_SMARTSPACE_ID"
private const val PACKAGE_NAME = "com.android.systemui"
private const val APP_NAME = "SystemUI"
private const val SESSION_ARTIST = "artist"
@@ -364,13 +364,14 @@
fun testOnSmartspaceMediaDataLoaded_hasNewMediaTarget_callsListener() {
smartspaceMediaDataProvider.onTargetsAvailable(listOf(mediaSmartspaceTarget))
verify(listener).onSmartspaceMediaDataLoaded(
- eq(KEY_MEDIA_SMARTSPACE), eq(mediaSmartspaceTarget))
+ eq(KEY_MEDIA_SMARTSPACE), eq(mediaSmartspaceTarget), eq(false))
}
@Test
fun testOnSmartspaceMediaDataLoaded_hasNoneMediaTarget_notCallsListener() {
smartspaceMediaDataProvider.onTargetsAvailable(listOf())
- verify(listener, never()).onSmartspaceMediaDataLoaded(anyObject(), anyObject())
+ verify(listener, never())
+ .onSmartspaceMediaDataLoaded(anyObject(), anyObject(), anyBoolean())
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt
index a974421..c6aef4a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt
@@ -30,6 +30,7 @@
import com.android.systemui.statusbar.SysuiStatusBarStateController
import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
+import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.animation.UniqueObjectHostView
import org.junit.Assert.assertNotNull
@@ -79,6 +80,8 @@
private lateinit var wakefulnessLifecycle: WakefulnessLifecycle
@Mock
private lateinit var statusBarKeyguardViewManager: StatusBarKeyguardViewManager
+ @Mock
+ private lateinit var configurationController: ConfigurationController
@Captor
private lateinit var wakefullnessObserver: ArgumentCaptor<(WakefulnessLifecycle.Observer)>
@Captor
@@ -98,6 +101,7 @@
bypassController,
mediaCarouselController,
notificationLockscreenUserManager,
+ configurationController,
wakefulnessLifecycle,
statusBarKeyguardViewManager)
verify(wakefulnessLifecycle).addObserver(wakefullnessObserver.capture())
diff --git a/packages/SystemUI/tests/src/com/android/systemui/people/PeopleSpaceUtilsTest.java b/packages/SystemUI/tests/src/com/android/systemui/people/PeopleSpaceUtilsTest.java
index 8983ff8..fd28c2c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/people/PeopleSpaceUtilsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/people/PeopleSpaceUtilsTest.java
@@ -220,8 +220,8 @@
when(mMockContext.getString(R.string.basic_status)).thenReturn(
mContext.getString(R.string.basic_status));
when(mMockContext.getPackageManager()).thenReturn(mPackageManager);
- when(mMockContext.getString(R.string.over_timestamp)).thenReturn(
- mContext.getString(R.string.over_timestamp));
+ when(mMockContext.getString(R.string.over_two_weeks_timestamp)).thenReturn(
+ mContext.getString(R.string.over_two_weeks_timestamp));
when(mPackageManager.getApplicationIcon(anyString())).thenReturn(null);
when(mNotificationEntryManager.getVisibleNotifications())
.thenReturn(List.of(mNotificationEntry1, mNotificationEntry2, mNotificationEntry3));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/people/PeopleTileViewHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/people/PeopleTileViewHelperTest.java
index 7172307..3b56f22 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/people/PeopleTileViewHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/people/PeopleTileViewHelperTest.java
@@ -148,8 +148,8 @@
when(mMockContext.getString(R.string.birthday_status)).thenReturn(
mContext.getString(R.string.birthday_status));
when(mMockContext.getPackageManager()).thenReturn(mPackageManager);
- when(mMockContext.getString(R.string.over_timestamp)).thenReturn(
- mContext.getString(R.string.over_timestamp));
+ when(mMockContext.getString(R.string.over_two_weeks_timestamp)).thenReturn(
+ mContext.getString(R.string.over_two_weeks_timestamp));
Configuration configuration = mock(Configuration.class);
DisplayMetrics displayMetrics = mock(DisplayMetrics.class);
Resources resources = mock(Resources.class);
@@ -325,7 +325,7 @@
TextView statusContent = (TextView) result.findViewById(R.id.text_content);
assertEquals(View.VISIBLE, statusContent.getVisibility());
assertEquals(statusContent.getText(), mContext.getString(R.string.birthday_status));
- assertThat(statusContent.getMaxLines()).isEqualTo(3);
+ assertThat(statusContent.getMaxLines()).isEqualTo(2);
mOptions.putInt(OPTION_APPWIDGET_MIN_WIDTH,
getSizeInDp(R.dimen.required_width_for_medium) - 1);
@@ -364,7 +364,7 @@
statusContent = (TextView) largeResult.findViewById(R.id.text_content);
assertEquals(View.VISIBLE, statusContent.getVisibility());
assertEquals(statusContent.getText(), mContext.getString(R.string.birthday_status));
- assertThat(statusContent.getMaxLines()).isEqualTo(3);
+ assertThat(statusContent.getMaxLines()).isEqualTo(2);
}
@Test
@@ -390,7 +390,7 @@
// Has status.
TextView statusContent = (TextView) result.findViewById(R.id.text_content);
assertEquals(statusContent.getText(), GAME_DESCRIPTION);
- assertThat(statusContent.getMaxLines()).isEqualTo(3);
+ assertThat(statusContent.getMaxLines()).isEqualTo(2);
mOptions.putInt(OPTION_APPWIDGET_MIN_WIDTH,
getSizeInDp(R.dimen.required_width_for_medium) - 1);
@@ -431,7 +431,7 @@
statusContent = (TextView) largeResult.findViewById(R.id.text_content);
assertEquals(View.VISIBLE, statusContent.getVisibility());
assertEquals(statusContent.getText(), GAME_DESCRIPTION);
- assertThat(statusContent.getMaxLines()).isEqualTo(3);
+ assertThat(statusContent.getMaxLines()).isEqualTo(2);
}
@Test
@@ -620,7 +620,7 @@
TextView statusContent = (TextView) result.findViewById(R.id.text_content);
assertEquals(View.VISIBLE, statusContent.getVisibility());
assertEquals(statusContent.getText(), MISSED_CALL);
- assertThat(statusContent.getMaxLines()).isEqualTo(3);
+ assertThat(statusContent.getMaxLines()).isEqualTo(2);
mOptions.putInt(OPTION_APPWIDGET_MIN_WIDTH,
getSizeInDp(R.dimen.required_width_for_medium) - 1);
@@ -658,7 +658,7 @@
statusContent = (TextView) largeResult.findViewById(R.id.text_content);
assertEquals(View.VISIBLE, statusContent.getVisibility());
assertEquals(statusContent.getText(), MISSED_CALL);
- assertThat(statusContent.getMaxLines()).isEqualTo(3);
+ assertThat(statusContent.getMaxLines()).isEqualTo(2);
}
@Test
@@ -684,7 +684,7 @@
TextView statusContent = (TextView) result.findViewById(R.id.text_content);
assertEquals(View.VISIBLE, statusContent.getVisibility());
assertEquals(statusContent.getText(), NOTIFICATION_CONTENT);
- assertThat(statusContent.getMaxLines()).isEqualTo(3);
+ assertThat(statusContent.getMaxLines()).isEqualTo(2);
// Has a single message, no count shown.
assertEquals(View.GONE, result.findViewById(R.id.messages_count).getVisibility());
@@ -718,7 +718,7 @@
assertEquals(name.getText(), NAME);
assertEquals(View.GONE, largeResult.findViewById(R.id.subtext).getVisibility());
assertEquals(View.GONE, largeResult.findViewById(R.id.predefined_icon).getVisibility());
- assertEquals(View.GONE, largeResult.findViewById(R.id.scrim_layout).getVisibility());
+ assertEquals(largeResult.findViewById(R.id.scrim_layout), null);
// Has availability.
assertEquals(View.VISIBLE, largeResult.findViewById(R.id.availability).getVisibility());
// Has person icon.
@@ -728,7 +728,7 @@
statusContent = (TextView) largeResult.findViewById(R.id.text_content);
assertEquals(View.VISIBLE, statusContent.getVisibility());
assertEquals(statusContent.getText(), NOTIFICATION_CONTENT);
- assertThat(statusContent.getMaxLines()).isEqualTo(3);
+ assertThat(statusContent.getMaxLines()).isEqualTo(2);
// Has a single message, no count shown.
assertEquals(View.GONE, largeResult.findViewById(R.id.messages_count).getVisibility());
@@ -761,7 +761,7 @@
assertEquals(statusContent.getText(), NOTIFICATION_CONTENT);
// Subtract one from lines because sender is included.
- assertThat(statusContent.getMaxLines()).isEqualTo(2);
+ assertThat(statusContent.getMaxLines()).isEqualTo(1);
// Has a single message, no count shown.
assertEquals(View.GONE, result.findViewById(R.id.messages_count).getVisibility());
@@ -808,7 +808,7 @@
assertEquals(statusContent.getText(), NOTIFICATION_CONTENT);
// Subtract one from lines because sender is included.
- assertThat(statusContent.getMaxLines()).isEqualTo(2);
+ assertThat(statusContent.getMaxLines()).isEqualTo(1);
// Has a single message, no count shown.
assertEquals(View.GONE, largeResult.findViewById(R.id.messages_count).getVisibility());
@@ -838,7 +838,7 @@
TextView statusContent = (TextView) result.findViewById(R.id.text_content);
assertEquals(View.VISIBLE, statusContent.getVisibility());
assertEquals(statusContent.getText(), NOTIFICATION_CONTENT);
- assertThat(statusContent.getMaxLines()).isEqualTo(3);
+ assertThat(statusContent.getMaxLines()).isEqualTo(2);
// Has two messages, show count.
assertEquals(View.VISIBLE, result.findViewById(R.id.messages_count).getVisibility());
@@ -881,7 +881,7 @@
statusContent = (TextView) largeResult.findViewById(R.id.text_content);
assertEquals(View.VISIBLE, statusContent.getVisibility());
assertEquals(statusContent.getText(), NOTIFICATION_CONTENT);
- assertThat(statusContent.getMaxLines()).isEqualTo(3);
+ assertThat(statusContent.getMaxLines()).isEqualTo(2);
// Has two messages, show count.
assertEquals(View.VISIBLE, largeResult.findViewById(R.id.messages_count).getVisibility());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSDetailTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSDetailTest.java
index ba2b37c..75cf855 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSDetailTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSDetailTest.java
@@ -20,7 +20,9 @@
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -75,6 +77,7 @@
mQsPanelController = mock(QSPanelController.class);
mQuickHeader = mock(QuickStatusBarHeader.class);
mQsDetail.setQsPanel(mQsPanelController, mQuickHeader, mock(QSFooter.class));
+ mQsDetail.mClipper = mock(QSDetailClipper.class);
mMockDetailAdapter = mock(DetailAdapter.class);
when(mMockDetailAdapter.createDetailView(any(), any(), any()))
@@ -115,6 +118,62 @@
}
@Test
+ public void testShowDetail_ShouldAnimate() {
+ mTestableLooper.processAllMessages();
+
+ when(mMockDetailAdapter.shouldAnimate()).thenReturn(true);
+ mQsDetail.setFullyExpanded(true);
+
+ mQsDetail.handleShowingDetail(mMockDetailAdapter, 0, 0, false);
+ verify(mQsDetail.mClipper).updateCircularClip(eq(true) /* animate */, anyInt(), anyInt(),
+ eq(true) /* in */, any());
+ clearInvocations(mQsDetail.mClipper);
+
+ mQsDetail.handleShowingDetail(null, 0, 0, false);
+ verify(mQsDetail.mClipper).updateCircularClip(eq(true) /* animate */, anyInt(), anyInt(),
+ eq(false) /* in */, any());
+ }
+
+ @Test
+ public void testShowDetail_ShouldNotAnimate() {
+ mTestableLooper.processAllMessages();
+
+ when(mMockDetailAdapter.shouldAnimate()).thenReturn(false);
+ mQsDetail.setFullyExpanded(true);
+
+ mQsDetail.handleShowingDetail(mMockDetailAdapter, 0, 0, false);
+ verify(mQsDetail.mClipper).updateCircularClip(eq(false) /* animate */, anyInt(), anyInt(),
+ eq(true) /* in */, any());
+ clearInvocations(mQsDetail.mClipper);
+
+ mQsDetail.handleShowingDetail(null, 0, 0, false);
+ verify(mQsDetail.mClipper).updateCircularClip(eq(false) /* animate */, anyInt(), anyInt(),
+ eq(false) /* in */, any());
+ }
+
+ @Test
+ public void testDoneButton_CloseDetailPanel() {
+ mTestableLooper.processAllMessages();
+
+ when(mMockDetailAdapter.onDoneButtonClicked()).thenReturn(false);
+
+ mQsDetail.handleShowingDetail(mMockDetailAdapter, 0, 0, false);
+ mQsDetail.requireViewById(android.R.id.button1).performClick();
+ verify(mQsPanelController).closeDetail();
+ }
+
+ @Test
+ public void testDoneButton_KeepDetailPanelOpen() {
+ mTestableLooper.processAllMessages();
+
+ when(mMockDetailAdapter.onDoneButtonClicked()).thenReturn(true);
+
+ mQsDetail.handleShowingDetail(mMockDetailAdapter, 0, 0, false);
+ mQsDetail.requireViewById(android.R.id.button1).performClick();
+ verify(mQsPanelController, never()).closeDetail();
+ }
+
+ @Test
public void testMoreSettingsButton() {
mTestableLooper.processAllMessages();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt
index 6cf3434..f17fe9a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt
@@ -39,6 +39,7 @@
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.qs.QSHost
import com.android.systemui.qs.logging.QSLogger
+import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.capture
import com.android.systemui.util.mockito.eq
@@ -87,6 +88,8 @@
private lateinit var serviceInfo: ControlsServiceInfo
@Mock
private lateinit var uiEventLogger: UiEventLogger
+ @Mock
+ private lateinit var keyguardStateController: KeyguardStateController
@Captor
private lateinit var listingCallbackCaptor:
ArgumentCaptor<ControlsListingController.ControlsListingCallback>
@@ -109,7 +112,8 @@
`when`(qsHost.context).thenReturn(spiedContext)
`when`(qsHost.uiEventLogger).thenReturn(uiEventLogger)
`when`(controlsComponent.isEnabled()).thenReturn(true)
- secureSettings.putInt(Settings.Secure.POWER_MENU_LOCKED_SHOW_CONTENT, 1)
+ `when`(keyguardStateController.isUnlocked()).thenReturn(true)
+ secureSettings.putInt(Settings.Secure.LOCKSCREEN_SHOW_CONTROLS, 1)
setupControlsComponent()
@@ -306,7 +310,8 @@
statusBarStateController,
activityStarter,
qsLogger,
- controlsComponent
+ controlsComponent,
+ keyguardStateController
)
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java
index e894b7b..7533cf1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java
@@ -92,6 +92,7 @@
public class QuickAccessWalletTileTest extends SysuiTestCase {
private static final String CARD_ID = "card_id";
+ private static final String LABEL = "QAW";
private static final Icon CARD_IMAGE =
Icon.createWithBitmap(Bitmap.createBitmap(70, 50, Bitmap.Config.ARGB_8888));
@@ -141,6 +142,7 @@
when(mHost.getContext()).thenReturn(mSpiedContext);
when(mHost.getUiEventLogger()).thenReturn(mUiEventLogger);
when(mFeatureFlags.isQuickAccessWalletEnabled()).thenReturn(true);
+ when(mQuickAccessWalletClient.getServiceLabel()).thenReturn(LABEL);
when(mQuickAccessWalletClient.isWalletFeatureAvailable()).thenReturn(true);
when(mQuickAccessWalletClient.isWalletServiceAvailable()).thenReturn(true);
@@ -248,13 +250,19 @@
mTile.handleUpdateState(state, null);
- assertEquals(mContext.getString(R.string.wallet_title), state.label.toString());
+ assertEquals(LABEL, state.label.toString());
assertTrue(state.label.toString().contentEquals(state.contentDescription));
assertEquals(icon, state.icon);
}
@Test
- public void testGetTileLabel() {
+ public void testGetTileLabel_serviceLabelExists() {
+ assertEquals(LABEL, mTile.getTileLabel().toString());
+ }
+
+ @Test
+ public void testGetTileLabel_serviceLabelDoesNotExist() {
+ when(mQuickAccessWalletClient.getServiceLabel()).thenReturn(null);
assertEquals(mContext.getString(R.string.wallet_title), mTile.getTileLabel().toString());
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/system/RemoteTransitionTest.java b/packages/SystemUI/tests/src/com/android/systemui/shared/system/RemoteTransitionTest.java
index d1259d3..360eef9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/system/RemoteTransitionTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/system/RemoteTransitionTest.java
@@ -68,8 +68,8 @@
.addChange(TRANSIT_CLOSE, 0 /* flags */)
.addChange(TRANSIT_OPEN, FLAG_IS_WALLPAPER).build();
// Check non-wallpaper extraction
- RemoteAnimationTargetCompat[] wrapped =
- RemoteAnimationTargetCompat.wrap(combined, false /* wallpapers */);
+ RemoteAnimationTargetCompat[] wrapped = RemoteAnimationTargetCompat.wrap(combined,
+ false /* wallpapers */, mock(SurfaceControl.Transaction.class), null /* leashes */);
assertEquals(2, wrapped.length);
int changeLayer = -1;
int closeLayer = -1;
@@ -86,8 +86,8 @@
assertTrue(closeLayer < changeLayer);
// Check wallpaper extraction
- RemoteAnimationTargetCompat[] wallps =
- RemoteAnimationTargetCompat.wrap(combined, true /* wallpapers */);
+ RemoteAnimationTargetCompat[] wallps = RemoteAnimationTargetCompat.wrap(combined,
+ true /* wallpapers */, mock(SurfaceControl.Transaction.class), null /* leashes */);
assertEquals(1, wallps.length);
assertTrue(wallps[0].prefixOrderIndex < closeLayer);
assertEquals(MODE_OPENING, wallps[0].mode);
@@ -95,16 +95,15 @@
@Test
public void testLegacyTargetWrapper() {
+ TransitionInfo tinfo = new TransitionInfoBuilder(TRANSIT_CLOSE)
+ .addChange(TRANSIT_CHANGE, FLAG_TRANSLUCENT).build();
+ final TransitionInfo.Change change = tinfo.getChanges().get(0);
final Rect endBounds = new Rect(40, 60, 140, 200);
- final TransitionInfo.Change change =
- new TransitionInfo.Change(null /* token */, null /* leash */);
change.setTaskInfo(createTaskInfo(1 /* taskId */, ACTIVITY_TYPE_HOME));
- change.setMode(TRANSIT_CHANGE);
change.setEndAbsBounds(endBounds);
change.setEndRelOffset(0, 0);
- change.setFlags(FLAG_TRANSLUCENT);
- final RemoteAnimationTargetCompat wrapped =
- new RemoteAnimationTargetCompat(change, 0 /* order */);
+ final RemoteAnimationTargetCompat wrapped = new RemoteAnimationTargetCompat(change,
+ 0 /* order */, tinfo, mock(SurfaceControl.Transaction.class));
assertEquals(ACTIVITY_TYPE_HOME, wrapped.activityType);
assertEquals(new Rect(0, 0, 100, 140), wrapped.localBounds);
assertEquals(endBounds, wrapped.screenSpaceBounds);
@@ -122,7 +121,7 @@
TransitionInfoBuilder addChange(@WindowManager.TransitionType int mode,
@TransitionInfo.ChangeFlags int flags) {
final TransitionInfo.Change change =
- new TransitionInfo.Change(null /* token */, null /* leash */);
+ new TransitionInfo.Change(null /* token */, createMockSurface(true));
change.setMode(mode);
change.setFlags(flags);
mInfo.addChange(change);
@@ -138,6 +137,7 @@
SurfaceControl sc = mock(SurfaceControl.class);
if (valid) {
doReturn(true).when(sc).isValid();
+ doReturn("TestSurface").when(sc).toString();
}
return sc;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
index 6f0ae22..b8db115 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
@@ -46,6 +46,7 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.IActivityManager;
import android.app.Instrumentation;
import android.app.admin.DevicePolicyManager;
import android.app.trust.TrustManager;
@@ -69,6 +70,7 @@
import androidx.test.runner.AndroidJUnit4;
import com.android.internal.app.IBatteryStats;
+import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.settingslib.Utils;
import com.android.settingslib.fuelgauge.BatteryStatus;
@@ -141,6 +143,10 @@
private KeyguardIndicationRotateTextViewController mRotateTextViewController;
@Mock
private FalsingManager mFalsingManager;
+ @Mock
+ private LockPatternUtils mLockPatternUtils;
+ @Mock
+ private IActivityManager mIActivityManager;
@Captor
private ArgumentCaptor<DockManager.AlignmentStateListener> mAlignmentListener;
@Captor
@@ -208,7 +214,8 @@
mController = new KeyguardIndicationController(mContext, mWakeLockBuilder,
mKeyguardStateController, mStatusBarStateController, mKeyguardUpdateMonitor,
mDockManager, mBroadcastDispatcher, mDevicePolicyManager, mIBatteryStats,
- mUserManager, mExecutor, mFalsingManager);
+ mUserManager, mExecutor, mFalsingManager, mLockPatternUtils, mIActivityManager);
+ mController.init();
mController.setIndicationArea(mIndicationArea);
verify(mStatusBarStateController).addCallback(mStatusBarStateListenerCaptor.capture());
mStatusBarStateListener = mStatusBarStateListenerCaptor.getValue();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
new file mode 100644
index 0000000..18b6c30
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
@@ -0,0 +1,225 @@
+package com.android.systemui.statusbar
+
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import android.testing.TestableLooper.RunWithLooper
+import android.util.DisplayMetrics
+import androidx.test.filters.SmallTest
+import com.android.systemui.ExpandHelper
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.classifier.FalsingCollector
+import com.android.systemui.media.MediaHierarchyManager
+import com.android.systemui.plugins.FalsingManager
+import com.android.systemui.plugins.qs.QS
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
+import com.android.systemui.statusbar.notification.row.NotificationTestHelper
+import com.android.systemui.statusbar.notification.stack.AmbientState
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
+import com.android.systemui.statusbar.phone.KeyguardBypassController
+import com.android.systemui.statusbar.phone.LockscreenGestureLogger
+import com.android.systemui.statusbar.phone.NotificationPanelViewController
+import com.android.systemui.statusbar.phone.ScrimController
+import com.android.systemui.statusbar.phone.StatusBar
+import com.android.systemui.statusbar.policy.ConfigurationController
+import org.junit.After
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertNotNull
+import org.junit.Assert.assertNull
+import org.junit.Assert.assertTrue
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.anyBoolean
+import org.mockito.ArgumentMatchers.anyFloat
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.ArgumentMatchers.anyLong
+import org.mockito.Mock
+import org.mockito.Mockito
+import org.mockito.Mockito.clearInvocations
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.junit.MockitoJUnit
+import org.mockito.Mockito.`when` as whenever
+
+private fun <T> anyObject(): T {
+ return Mockito.anyObject<T>()
+}
+
+@SmallTest
+@RunWithLooper(setAsMainLooper = true)
+@RunWith(AndroidTestingRunner::class)
+class LockscreenShadeTransitionControllerTest : SysuiTestCase() {
+
+ lateinit var transitionController: LockscreenShadeTransitionController
+ lateinit var row: ExpandableNotificationRow
+ @Mock lateinit var statusbarStateController: SysuiStatusBarStateController
+ @Mock lateinit var lockscreenGestureLogger: LockscreenGestureLogger
+ @Mock lateinit var keyguardBypassController: KeyguardBypassController
+ @Mock lateinit var lockScreenUserManager: NotificationLockscreenUserManager
+ @Mock lateinit var falsingCollector: FalsingCollector
+ @Mock lateinit var ambientState: AmbientState
+ @Mock lateinit var displayMetrics: DisplayMetrics
+ @Mock lateinit var mediaHierarchyManager: MediaHierarchyManager
+ @Mock lateinit var scrimController: ScrimController
+ @Mock lateinit var configurationController: ConfigurationController
+ @Mock lateinit var falsingManager: FalsingManager
+ @Mock lateinit var notificationPanelController: NotificationPanelViewController
+ @Mock lateinit var nsslController: NotificationStackScrollLayoutController
+ @Mock lateinit var featureFlags: FeatureFlags
+ @Mock lateinit var stackscroller: NotificationStackScrollLayout
+ @Mock lateinit var expandHelperCallback: ExpandHelper.Callback
+ @Mock lateinit var statusbar: StatusBar
+ @Mock lateinit var qS: QS
+ @JvmField @Rule val mockito = MockitoJUnit.rule()
+
+ @Before
+ fun setup() {
+ val helper = NotificationTestHelper(
+ mContext,
+ mDependency,
+ TestableLooper.get(this))
+ row = helper.createRow()
+ transitionController = LockscreenShadeTransitionController(
+ statusBarStateController = statusbarStateController,
+ lockscreenGestureLogger = lockscreenGestureLogger,
+ keyguardBypassController = keyguardBypassController,
+ lockScreenUserManager = lockScreenUserManager,
+ falsingCollector = falsingCollector,
+ ambientState = ambientState,
+ displayMetrics = displayMetrics,
+ mediaHierarchyManager = mediaHierarchyManager,
+ scrimController = scrimController,
+ featureFlags = featureFlags,
+ context = context,
+ configurationController = configurationController,
+ falsingManager = falsingManager
+ )
+ whenever(nsslController.view).thenReturn(stackscroller)
+ whenever(nsslController.expandHelperCallback).thenReturn(expandHelperCallback)
+ transitionController.notificationPanelController = notificationPanelController
+ transitionController.statusbar = statusbar
+ transitionController.qS = qS
+ transitionController.setStackScroller(nsslController)
+ whenever(statusbarStateController.state).thenReturn(StatusBarState.KEYGUARD)
+ whenever(nsslController.isInLockedDownShade).thenReturn(false)
+ whenever(qS.isFullyCollapsed).thenReturn(true)
+ whenever(lockScreenUserManager.userAllowsPrivateNotificationsInPublic(anyInt())).thenReturn(
+ true)
+ whenever(lockScreenUserManager.shouldShowLockscreenNotifications()).thenReturn(true)
+ whenever(lockScreenUserManager.isLockscreenPublicMode(anyInt())).thenReturn(true)
+ whenever(falsingCollector.shouldEnforceBouncer()).thenReturn(false)
+ whenever(keyguardBypassController.bypassEnabled).thenReturn(false)
+ clearInvocations(statusbar)
+ }
+
+ @After
+ fun tearDown() {
+ transitionController.dragDownAnimator?.cancel()
+ }
+
+ @Test
+ fun testCantDragDownWhenQSExpanded() {
+ assertTrue("Can't drag down on keyguard", transitionController.canDragDown())
+ whenever(qS.isFullyCollapsed).thenReturn(false)
+ assertFalse("Can drag down when QS is expanded", transitionController.canDragDown())
+ }
+
+ @Test
+ fun testCanDragDownInLockedDownShade() {
+ whenever(statusbarStateController.state).thenReturn(StatusBarState.SHADE_LOCKED)
+ assertFalse("Can drag down in shade locked", transitionController.canDragDown())
+ whenever(nsslController.isInLockedDownShade).thenReturn(true)
+ assertTrue("Can't drag down in locked down shade", transitionController.canDragDown())
+ }
+
+ @Test
+ fun testGoingToLockedShade() {
+ transitionController.goToLockedShade(null)
+ verify(statusbarStateController).setState(StatusBarState.SHADE_LOCKED)
+ }
+
+ @Test
+ fun testGoToLockedShadeOnlyOnKeyguard() {
+ whenever(statusbarStateController.state).thenReturn(StatusBarState.SHADE_LOCKED)
+ transitionController.goToLockedShade(null)
+ whenever(statusbarStateController.state).thenReturn(StatusBarState.SHADE)
+ transitionController.goToLockedShade(null)
+ whenever(statusbarStateController.state).thenReturn(StatusBarState.FULLSCREEN_USER_SWITCHER)
+ transitionController.goToLockedShade(null)
+ verify(statusbarStateController, never()).setState(anyInt())
+ }
+
+ @Test
+ fun testDontGoWhenShadeDisabled() {
+ whenever(statusbar.isShadeDisabled).thenReturn(true)
+ transitionController.goToLockedShade(null)
+ verify(statusbarStateController, never()).setState(anyInt())
+ }
+
+ @Test
+ fun testUserExpandsViewOnGoingToFullShade() {
+ assertFalse("Row shouldn't be user expanded yet", row.isUserExpanded)
+ transitionController.goToLockedShade(row)
+ assertTrue("Row wasn't user expanded on drag down", row.isUserExpanded)
+ }
+
+ @Test
+ fun testTriggeringBouncerWhenPrivateNotificationsArentAllowed() {
+ whenever(lockScreenUserManager.userAllowsPrivateNotificationsInPublic(anyInt())).thenReturn(
+ false)
+ transitionController.goToLockedShade(null)
+ verify(statusbarStateController, never()).setState(anyInt())
+ verify(statusbarStateController).setLeaveOpenOnKeyguardHide(true)
+ verify(statusbar).showBouncerWithDimissAndCancelIfKeyguard(anyObject(), anyObject())
+ }
+
+ @Test
+ fun testTriggeringBouncerNoNotificationsOnLockscreen() {
+ whenever(lockScreenUserManager.shouldShowLockscreenNotifications()).thenReturn(false)
+ transitionController.goToLockedShade(null)
+ verify(statusbarStateController, never()).setState(anyInt())
+ verify(statusbarStateController).setLeaveOpenOnKeyguardHide(true)
+ verify(statusbar).showBouncerWithDimissAndCancelIfKeyguard(anyObject(), anyObject())
+ }
+
+ @Test
+ fun testGoToLockedShadeCreatesQSAnimation() {
+ transitionController.goToLockedShade(null)
+ verify(statusbarStateController).setState(StatusBarState.SHADE_LOCKED)
+ verify(notificationPanelController).animateToFullShade(anyLong())
+ assertNotNull(transitionController.dragDownAnimator)
+ }
+
+ @Test
+ fun testGoToLockedShadeDoesntCreateQSAnimation() {
+ transitionController.goToLockedShade(null, needsQSAnimation = false)
+ verify(statusbarStateController).setState(StatusBarState.SHADE_LOCKED)
+ verify(notificationPanelController).animateToFullShade(anyLong())
+ assertNull(transitionController.dragDownAnimator)
+ }
+
+ @Test
+ fun testDragDownAmountDoesntCallOutInLockedDownShade() {
+ whenever(nsslController.isInLockedDownShade).thenReturn(true)
+ transitionController.dragDownAmount = 10f
+ verify(nsslController, never()).setTransitionToFullShadeAmount(anyFloat())
+ verify(mediaHierarchyManager, never()).setTransitionToFullShadeAmount(anyFloat())
+ verify(scrimController, never()).setTransitionToFullShadeProgress(anyFloat())
+ verify(notificationPanelController, never()).setTransitionToFullShadeAmount(anyFloat(),
+ anyBoolean(), anyLong())
+ verify(qS, never()).setTransitionToFullShadeAmount(anyFloat(), anyBoolean())
+ }
+
+ @Test
+ fun testDragDownAmountCallsOut() {
+ transitionController.dragDownAmount = 10f
+ verify(nsslController).setTransitionToFullShadeAmount(anyFloat())
+ verify(mediaHierarchyManager).setTransitionToFullShadeAmount(anyFloat())
+ verify(scrimController).setTransitionToFullShadeProgress(anyFloat())
+ verify(notificationPanelController).setTransitionToFullShadeAmount(anyFloat(),
+ anyBoolean(), anyLong())
+ verify(qS).setTransitionToFullShadeAmount(anyFloat(), anyBoolean())
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
index 2a50273..0c65830 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
@@ -16,9 +16,11 @@
package com.android.systemui.statusbar;
+import static android.app.NotificationManager.IMPORTANCE_HIGH;
import static android.app.NotificationManager.IMPORTANCE_LOW;
import static android.content.Intent.ACTION_USER_SWITCHED;
+import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_ALERTING;
import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_MEDIA_CONTROLS;
import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_PEOPLE;
import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_SILENT;
@@ -55,6 +57,7 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.NotificationLockscreenUserManager.KeyguardNotificationSuppressor;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
@@ -383,13 +386,44 @@
assertTrue(mLockscreenUserManager.shouldShowOnKeyguard(entry));
}
+ @Test
+ public void testKeyguardNotificationSuppressors() {
+ // GIVEN a notification that should be shown on the lockscreen
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 1);
+ final NotificationEntry entry = new NotificationEntryBuilder()
+ .setImportance(IMPORTANCE_HIGH)
+ .build();
+ entry.setBucket(BUCKET_ALERTING);
+
+ // WHEN a suppressor is added that filters out all entries
+ FakeKeyguardSuppressor suppressor = new FakeKeyguardSuppressor();
+ mLockscreenUserManager.addKeyguardNotificationSuppressor(suppressor);
+
+ // THEN it's filtered out
+ assertFalse(mLockscreenUserManager.shouldShowOnKeyguard(entry));
+
+ // WHEN the suppressor no longer filters out entries
+ suppressor.setShouldSuppress(false);
+
+ // THEN it's no longer filtered out
+ assertTrue(mLockscreenUserManager.shouldShowOnKeyguard(entry));
+ }
+
private class TestNotificationLockscreenUserManager
extends NotificationLockscreenUserManagerImpl {
public TestNotificationLockscreenUserManager(Context context) {
- super(context, mBroadcastDispatcher, mDevicePolicyManager, mUserManager,
- mClickNotifier, NotificationLockscreenUserManagerTest.this.mKeyguardManager,
- mStatusBarStateController, Handler.createAsync(Looper.myLooper()),
- mDeviceProvisionedController, mKeyguardStateController);
+ super(
+ context,
+ mBroadcastDispatcher,
+ mDevicePolicyManager,
+ mUserManager,
+ mClickNotifier,
+ NotificationLockscreenUserManagerTest.this.mKeyguardManager,
+ mStatusBarStateController,
+ Handler.createAsync(Looper.myLooper()),
+ mDeviceProvisionedController,
+ mKeyguardStateController);
}
public BroadcastReceiver getBaseBroadcastReceiverForTest() {
@@ -404,4 +438,17 @@
return mSettingsObserver;
}
}
+
+ private static class FakeKeyguardSuppressor implements KeyguardNotificationSuppressor {
+ private boolean mShouldSuppress = true;
+
+ @Override
+ public boolean shouldSuppressOnKeyguard(NotificationEntry entry) {
+ return mShouldSuppress;
+ }
+
+ public void setShouldSuppress(boolean shouldSuppress) {
+ mShouldSuppress = shouldSuppress;
+ }
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt
index 5366858..9b5c33d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt
@@ -16,7 +16,6 @@
package com.android.systemui.statusbar.lockscreen
-
import android.app.smartspace.SmartspaceManager
import android.app.smartspace.SmartspaceSession
import android.app.smartspace.SmartspaceSession.OnTargetsAvailableListener
@@ -415,8 +414,9 @@
clearInvocations(smartspaceManager)
clearInvocations(plugin)
- // WHEN we're asked to connect a second time
- controller.buildAndConnectView(fakeParent)
+ // WHEN we're asked to connect a second time and add to a parent
+ val view = controller.buildAndConnectView(fakeParent)
+ fakeParent.addView(view)
// THEN the existing view and session are reused
verify(smartspaceManager, never()).createSmartspaceSession(any())
@@ -424,8 +424,8 @@
assertEquals(fakeSmartspaceView, controller.view)
}
- private fun connectSession(): View {
- val view = controller.buildAndConnectView(fakeParent)
+ private fun connectSession() {
+ controller.buildAndConnectView(fakeParent)
verify(smartspaceSession)
.addOnTargetsAvailableListener(any(), capture(sessionListenerCaptor))
@@ -454,7 +454,7 @@
verify(fakeSmartspaceView).setDozeAmount(0.5f)
clearInvocations(fakeSmartspaceView)
- return view
+ fakeParent.addView(fakeSmartspaceView)
}
private fun setActiveUser(userHandle: UserHandle) {
@@ -515,4 +515,4 @@
}
private const val PRIVATE_LOCKSCREEN_SETTING =
- Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS
\ No newline at end of file
+ Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/DynamicPrivacyControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/DynamicPrivacyControllerTest.java
index 68cf66d..7d06abf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/DynamicPrivacyControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/DynamicPrivacyControllerTest.java
@@ -16,6 +16,8 @@
package com.android.systemui.statusbar.notification;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.mock;
@@ -60,13 +62,15 @@
mDynamicPrivacyController.setStatusBarKeyguardViewManager(
mock(StatusBarKeyguardViewManager.class));
mDynamicPrivacyController.addListener(mListener);
+ // Disable dynamic privacy by default
+ allowPrivateNotificationsInPublic(true);
}
@Test
public void testDynamicFalseWhenCannotSkipBouncer() {
enableDynamicPrivacy();
when(mKeyguardStateController.canDismissLockScreen()).thenReturn(false);
- Assert.assertFalse("can't skip bouncer but is dynamically unlocked",
+ assertFalse("can't skip bouncer but is dynamically unlocked",
mDynamicPrivacyController.isDynamicallyUnlocked());
}
@@ -102,9 +106,26 @@
verify(mListener).onDynamicPrivacyChanged();
}
- private void enableDynamicPrivacy() {
+ @Test
+ public void dynamicPrivacyOnlyWhenHidingPrivate() {
+ // Verify that when only hiding notifications, this isn't enabled
+ allowPrivateNotificationsInPublic(true);
when(mLockScreenUserManager.shouldHideNotifications(any())).thenReturn(
false);
+ assertFalse("Dynamic privacy shouldn't be enabled when only hiding notifications",
+ mDynamicPrivacyController.isDynamicPrivacyEnabled());
+ allowPrivateNotificationsInPublic(false);
+ assertTrue("Should be enabled when hiding notification contents",
+ mDynamicPrivacyController.isDynamicPrivacyEnabled());
+ }
+
+ private void enableDynamicPrivacy() {
+ allowPrivateNotificationsInPublic(false);
+ }
+
+ private void allowPrivateNotificationsInPublic(boolean allow) {
+ when(mLockScreenUserManager.userAllowsPrivateNotificationsInPublic(anyInt())).thenReturn(
+ allow);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
index 6459c0c..1be14b6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
@@ -190,16 +190,6 @@
mEntryManager = new NotificationEntryManager(
mLogger,
mGroupManager,
- () -> new NotificationRankingManager(
- () -> mNotificationMediaManager,
- mGroupManager,
- mHeadsUpManager,
- mock(NotificationFilter.class),
- mLogger,
- mock(NotificationSectionsFeatureManager.class),
- mock(PeopleNotificationIdentifier.class),
- mock(HighPriorityProvider.class)),
- mEnvironment,
mFeatureFlags,
() -> mNotificationRowBinder,
() -> mRemoteInputManager,
@@ -207,6 +197,17 @@
mock(ForegroundServiceDismissalFeatureController.class),
mock(IStatusBarService.class)
);
+ mEntryManager.setRanker(
+ new NotificationRankingManager(
+ () -> mNotificationMediaManager,
+ mGroupManager,
+ mHeadsUpManager,
+ mock(NotificationFilter.class),
+ mLogger,
+ mock(NotificationSectionsFeatureManager.class),
+ mock(PeopleNotificationIdentifier.class),
+ mock(HighPriorityProvider.class),
+ mEnvironment));
mEntryManager.setUpWithPresenter(mPresenter);
mEntryManager.addNotificationEntryListener(mEntryListener);
mEntryManager.addNotificationRemoveInterceptor(mRemoveInterceptor);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java
index b493b9a..b1eef4b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java
@@ -77,13 +77,16 @@
mock(StatusBarNotification.class);
@Mock
- ForegroundServiceController mFsc;
+ StatusBarStateController mStatusBarStateController;
@Mock
KeyguardEnvironment mEnvironment;
@Mock
- MediaFeatureFlag mMediaFeatureFlag;
+ ForegroundServiceController mFsc;
@Mock
- StatusBarStateController mStatusBarStateController;
+ NotificationLockscreenUserManager mUserManager;
+ @Mock
+ MediaFeatureFlag mMediaFeatureFlag;
+
private final IPackageManager mMockPackageManager = mock(IPackageManager.class);
private NotificationFilter mNotificationFilter;
@@ -127,7 +130,12 @@
mDependency,
TestableLooper.get(this));
mRow = testHelper.createRow();
- mNotificationFilter = new NotificationFilter(mStatusBarStateController, mMediaFeatureFlag);
+ mNotificationFilter = new NotificationFilter(
+ mStatusBarStateController,
+ mEnvironment,
+ mFsc,
+ mUserManager,
+ mMediaFeatureFlag);
}
@After
@@ -195,7 +203,11 @@
public void shouldFilterOtherNotificationWhenDisabled() {
// GIVEN that the media feature is disabled
when(mMediaFeatureFlag.getEnabled()).thenReturn(false);
- NotificationFilter filter = new NotificationFilter(mStatusBarStateController,
+ NotificationFilter filter = new NotificationFilter(
+ mStatusBarStateController,
+ mEnvironment,
+ mFsc,
+ mUserManager,
mMediaFeatureFlag);
// WHEN the media filter is asked about an entry
NotificationEntry otherEntry = new NotificationEntryBuilder().build();
@@ -208,7 +220,11 @@
public void shouldFilterOtherNotificationWhenEnabled() {
// GIVEN that the media feature is enabled
when(mMediaFeatureFlag.getEnabled()).thenReturn(true);
- NotificationFilter filter = new NotificationFilter(mStatusBarStateController,
+ NotificationFilter filter = new NotificationFilter(
+ mStatusBarStateController,
+ mEnvironment,
+ mFsc,
+ mUserManager,
mMediaFeatureFlag);
// WHEN the media filter is asked about an entry
NotificationEntry otherEntry = new NotificationEntryBuilder().build();
@@ -221,7 +237,11 @@
public void shouldFilterMediaNotificationWhenDisabled() {
// GIVEN that the media feature is disabled
when(mMediaFeatureFlag.getEnabled()).thenReturn(false);
- NotificationFilter filter = new NotificationFilter(mStatusBarStateController,
+ NotificationFilter filter = new NotificationFilter(
+ mStatusBarStateController,
+ mEnvironment,
+ mFsc,
+ mUserManager,
mMediaFeatureFlag);
// WHEN the media filter is asked about a media entry
final boolean shouldFilter = filter.shouldFilterOut(mMediaEntry);
@@ -233,7 +253,11 @@
public void shouldFilterMediaNotificationWhenEnabled() {
// GIVEN that the media feature is enabled
when(mMediaFeatureFlag.getEnabled()).thenReturn(true);
- NotificationFilter filter = new NotificationFilter(mStatusBarStateController,
+ NotificationFilter filter = new NotificationFilter(
+ mStatusBarStateController,
+ mEnvironment,
+ mFsc,
+ mUserManager,
mMediaFeatureFlag);
// WHEN the media filter is asked about a media entry
final boolean shouldFilter = filter.shouldFilterOut(mMediaEntry);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManagerTest.kt
index bdd4a01..c51c628 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManagerTest.kt
@@ -30,9 +30,11 @@
import com.android.systemui.SysuiTestCase
import com.android.systemui.statusbar.NotificationEntryHelper.modifyRanking
import com.android.systemui.statusbar.NotificationMediaManager
+import com.android.systemui.statusbar.notification.NotificationEntryManager.KeyguardEnvironment
import com.android.systemui.statusbar.notification.NotificationEntryManagerLogger
import com.android.systemui.statusbar.notification.NotificationFilter
import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.TYPE_FULL_PERSON
@@ -42,7 +44,6 @@
import com.android.systemui.statusbar.notification.stack.BUCKET_ALERTING
import com.android.systemui.statusbar.notification.stack.BUCKET_FOREGROUND_SERVICE
import com.android.systemui.statusbar.notification.stack.BUCKET_SILENT
-import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy
import com.android.systemui.statusbar.policy.HeadsUpManager
import com.google.common.truth.Truth.assertThat
import dagger.Lazy
@@ -79,9 +80,11 @@
mock(NotificationEntryManagerLogger::class.java),
sectionsManager,
personNotificationIdentifier,
- HighPriorityProvider(personNotificationIdentifier,
- mock(NotificationGroupManagerLegacy::class.java))
- )
+ HighPriorityProvider(
+ personNotificationIdentifier,
+ mock(NotificationGroupManagerLegacy::class.java)),
+ mock(KeyguardEnvironment::class.java)
+ )
}
@Test
@@ -486,7 +489,8 @@
logger: NotificationEntryManagerLogger,
sectionsFeatureManager: NotificationSectionsFeatureManager,
peopleNotificationIdentifier: PeopleNotificationIdentifier,
- highPriorityProvider: HighPriorityProvider
+ highPriorityProvider: HighPriorityProvider,
+ keyguardEnvironment: KeyguardEnvironment
) : NotificationRankingManager(
mediaManager,
groupManager,
@@ -495,7 +499,8 @@
logger,
sectionsFeatureManager,
peopleNotificationIdentifier,
- highPriorityProvider
+ highPriorityProvider,
+ keyguardEnvironment
) {
fun applyTestRankingMap(r: RankingMap) {
rankingMap = r
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SmartspaceDedupingCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SmartspaceDedupingCoordinatorTest.kt
new file mode 100644
index 0000000..a8db8d7
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SmartspaceDedupingCoordinatorTest.kt
@@ -0,0 +1,418 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.collection.coordinator
+
+import android.app.smartspace.SmartspaceTarget
+import android.content.ComponentName
+import android.os.UserHandle
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.plugins.BcSmartspaceDataPlugin.SmartspaceTargetListener
+import com.android.systemui.plugins.statusbar.StatusBarStateController
+import com.android.systemui.statusbar.NotificationLockscreenUserManager
+import com.android.systemui.statusbar.StatusBarState
+import com.android.systemui.statusbar.SysuiStatusBarStateController
+import com.android.systemui.statusbar.lockscreen.LockscreenSmartspaceController
+import com.android.systemui.statusbar.notification.NotificationEntryManager
+import com.android.systemui.statusbar.notification.collection.NotifPipeline
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
+import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter
+import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Pluggable
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener
+import com.android.systemui.util.concurrency.FakeExecutor
+import com.android.systemui.util.mockito.capture
+import com.android.systemui.util.time.FakeSystemClock
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertTrue
+import org.junit.Before
+import org.junit.Test
+import org.mockito.ArgumentCaptor
+import org.mockito.Captor
+import org.mockito.Mock
+import org.mockito.Mockito.`when`
+import org.mockito.Mockito.anyString
+import org.mockito.Mockito.clearInvocations
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+import java.util.concurrent.TimeUnit
+
+@SmallTest
+class SmartspaceDedupingCoordinatorTest : SysuiTestCase() {
+
+ @Mock
+ private lateinit var statusBarStateController: SysuiStatusBarStateController
+ @Mock
+ private lateinit var smartspaceController: LockscreenSmartspaceController
+ @Mock
+ private lateinit var notificationEntryManager: NotificationEntryManager
+ @Mock
+ private lateinit var notificationLockscreenUserManager: NotificationLockscreenUserManager
+ @Mock
+ private lateinit var notifPipeline: NotifPipeline
+ @Mock
+ private lateinit var pluggableListener: Pluggable.PluggableListener<NotifFilter>
+
+ @Captor
+ private lateinit var filterCaptor: ArgumentCaptor<NotifFilter>
+ @Captor
+ private lateinit var collectionListenerCaptor: ArgumentCaptor<NotifCollectionListener>
+ @Captor
+ private lateinit var stateListenerCaptor: ArgumentCaptor<StatusBarStateController.StateListener>
+ @Captor
+ private lateinit var smartspaceListenerCaptor: ArgumentCaptor<SmartspaceTargetListener>
+
+ private lateinit var filter: NotifFilter
+ private lateinit var collectionListener: NotifCollectionListener
+ private lateinit var statusBarListener: StatusBarStateController.StateListener
+ private lateinit var newTargetListener: SmartspaceTargetListener
+
+ private lateinit var entry1HasRecentlyAlerted: NotificationEntry
+ private lateinit var entry2HasNotRecentlyAlerted: NotificationEntry
+ private lateinit var entry3NotAssociatedWithTarget: NotificationEntry
+ private lateinit var entry4HasNotRecentlyAlerted: NotificationEntry
+ private lateinit var target1: SmartspaceTarget
+ private lateinit var target2: SmartspaceTarget
+ private lateinit var target4: SmartspaceTarget
+
+ private val clock = FakeSystemClock()
+ private val executor = FakeExecutor(clock)
+ private val now = clock.currentTimeMillis()
+
+ private lateinit var deduper: SmartspaceDedupingCoordinator
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+
+ // Mock out some behavior
+ `when`(statusBarStateController.state).thenReturn(StatusBarState.KEYGUARD)
+
+ // Build the deduper
+ deduper = SmartspaceDedupingCoordinator(
+ statusBarStateController,
+ smartspaceController,
+ notificationEntryManager,
+ notificationLockscreenUserManager,
+ notifPipeline,
+ executor,
+ clock
+ )
+
+ // Attach the deduper and capture the listeners/filters that it registers
+ deduper.attach(notifPipeline)
+
+ verify(notifPipeline).addPreGroupFilter(filterCaptor.capture())
+ filter = filterCaptor.value
+ filter.setInvalidationListener(pluggableListener)
+
+ verify(notifPipeline).addCollectionListener(capture(collectionListenerCaptor))
+ collectionListener = collectionListenerCaptor.value
+
+ verify(statusBarStateController).addCallback(capture(stateListenerCaptor))
+ statusBarListener = stateListenerCaptor.value
+
+ verify(smartspaceController).addListener(capture(smartspaceListenerCaptor))
+ newTargetListener = smartspaceListenerCaptor.value
+
+ // Initialize some test data
+ entry1HasRecentlyAlerted = NotificationEntryBuilder()
+ .setPkg(PACKAGE_1)
+ .setId(11)
+ .setLastAudiblyAlertedMs(now - 10000)
+ .build()
+ entry2HasNotRecentlyAlerted = NotificationEntryBuilder()
+ .setPkg(PACKAGE_2)
+ .setId(22)
+ .build()
+ entry3NotAssociatedWithTarget = NotificationEntryBuilder()
+ .setPkg("com.test.package.3")
+ .setId(33)
+ .setLastAudiblyAlertedMs(now - 10000)
+ .build()
+ entry4HasNotRecentlyAlerted = NotificationEntryBuilder()
+ .setPkg(PACKAGE_2)
+ .setId(44)
+ .build()
+
+ target1 = buildTargetFor(entry1HasRecentlyAlerted)
+ target2 = buildTargetFor(entry2HasNotRecentlyAlerted)
+ target4 = buildTargetFor(entry4HasNotRecentlyAlerted)
+ }
+
+ @Test
+ fun testBasicFiltering() {
+ // GIVEN a few notifications
+ addEntries(
+ entry2HasNotRecentlyAlerted,
+ entry3NotAssociatedWithTarget,
+ entry4HasNotRecentlyAlerted)
+
+ // WHEN we receive smartspace targets associated with entry 2 and 3
+ sendTargets(target2, target4)
+
+ // THEN both pipelines are rerun
+ verifyPipelinesInvalidated()
+
+ // THEN the first target is filtered out, but the other ones aren't
+ assertTrue(filter.shouldFilterOut(entry2HasNotRecentlyAlerted, now))
+ assertFalse(filter.shouldFilterOut(entry3NotAssociatedWithTarget, now))
+ assertFalse(filter.shouldFilterOut(entry4HasNotRecentlyAlerted, now))
+ }
+
+ @Test
+ fun testDoNotFilterRecentlyAlertedNotifs() {
+ // GIVEN one notif that recently alerted and a second that hasn't
+ addEntries(entry1HasRecentlyAlerted, entry2HasNotRecentlyAlerted)
+
+ // WHEN they become associated with smartspace targets
+ sendTargets(target1, target2)
+
+ // THEN neither is filtered (the first because it's recently alerted and the second
+ // because it's not in the first position
+ verifyPipelinesNotInvalidated()
+ assertFalse(filter.shouldFilterOut(entry1HasRecentlyAlerted, now))
+ assertFalse(filter.shouldFilterOut(entry2HasNotRecentlyAlerted, now))
+ }
+
+ @Test
+ fun testFilterAlertedButNotRecentNotifs() {
+ // GIVEN a notification that alerted, but a very long time ago
+ val entryOldAlert = NotificationEntryBuilder(entry1HasRecentlyAlerted)
+ .setLastAudiblyAlertedMs(now - 40000)
+ .build()
+ addEntries(entryOldAlert)
+
+ // WHEN it becomes part of smartspace
+ val target = buildTargetFor(entryOldAlert)
+ sendTargets(target)
+
+ // THEN it's still filtered out (because it's not in the alert window)
+ verifyPipelinesInvalidated()
+ assertTrue(filter.shouldFilterOut(entryOldAlert, now))
+ }
+
+ @Test
+ fun testExceptionExpires() {
+ // GIVEN a recently-alerted notif that is the primary smartspace target
+ addEntries(entry1HasRecentlyAlerted)
+ sendTargets(target1)
+ clearPipelineInvocations()
+
+ // WHEN we go beyond the target's exception window
+ clock.advanceTime(20000)
+
+ // THEN the pipeline is invalidated
+ verifyPipelinesInvalidated()
+ assertExecutorIsClear()
+ }
+
+ @Test
+ fun testExceptionIsEventuallyFiltered() {
+ // GIVEN a notif that has recently alerted
+ addEntries(entry1HasRecentlyAlerted)
+
+ // WHEN it becomes the primary smartspace target
+ sendTargets(target1)
+
+ // THEN it isn't filtered out (because it recently alerted)
+ assertFalse(filter.shouldFilterOut(entry1HasRecentlyAlerted, now))
+
+ // WHEN we pass the alert window
+ clock.advanceTime(20000)
+
+ // THEN the notif is once again filtered
+ assertTrue(filter.shouldFilterOut(entry1HasRecentlyAlerted, clock.uptimeMillis()))
+ }
+
+ @Test
+ fun testExceptionIsUpdated() {
+ // GIVEN a notif that has recently alerted and is the primary smartspace target
+ addEntries(entry1HasRecentlyAlerted)
+ sendTargets(target1)
+ clearPipelineInvocations()
+ assertFalse(filter.shouldFilterOut(entry1HasRecentlyAlerted, clock.uptimeMillis()))
+
+ // GIVEN the notif is updated with a much more recent alert time
+ NotificationEntryBuilder(entry1HasRecentlyAlerted)
+ .setLastAudiblyAlertedMs(clock.currentTimeMillis() - 500)
+ .apply(entry1HasRecentlyAlerted)
+ updateEntries(entry1HasRecentlyAlerted)
+ assertFalse(filter.shouldFilterOut(entry1HasRecentlyAlerted, clock.uptimeMillis()))
+
+ // WHEN we advance beyond the original exception window
+ clock.advanceTime(25000)
+
+ // THEN the original exception window doesn't fire
+ verifyPipelinesNotInvalidated()
+ assertFalse(filter.shouldFilterOut(entry1HasRecentlyAlerted, clock.uptimeMillis()))
+
+ // WHEN we advance beyond the new exception window
+ clock.advanceTime(4500)
+
+ // THEN the pipelines are invalidated and no more timeouts are scheduled
+ verifyPipelinesInvalidated()
+ assertExecutorIsClear()
+ assertTrue(filter.shouldFilterOut(entry1HasRecentlyAlerted, clock.uptimeMillis()))
+ }
+
+ @Test
+ fun testReplacementIsCanceled() {
+ // GIVEN a single notif and smartspace target
+ addEntries(entry1HasRecentlyAlerted)
+ sendTargets(target1)
+ clearPipelineInvocations()
+
+ // WHEN a higher-ranked target arrives
+ val newerEntry = NotificationEntryBuilder()
+ .setPkg(PACKAGE_2)
+ .setId(55)
+ .setLastAudiblyAlertedMs(now - 1000)
+ .build()
+ val newerTarget = buildTargetFor(newerEntry)
+ sendTargets(newerTarget, target1)
+
+ // THEN the timeout of the other target is canceled and it is no longer filtered
+ assertExecutorIsClear()
+ assertFalse(filter.shouldFilterOut(entry1HasRecentlyAlerted, clock.uptimeMillis()))
+ verifyPipelinesInvalidated()
+ clearPipelineInvocations()
+
+ // WHEN the entry associated with the newer target later arrives
+ addEntries(newerEntry)
+
+ // THEN the entry is not filtered out (because it recently alerted)
+ assertFalse(filter.shouldFilterOut(newerEntry, clock.uptimeMillis()))
+
+ // WHEN its exception window passes
+ clock.advanceTime(ALERT_WINDOW)
+
+ // THEN we go back to filtering it
+ verifyPipelinesInvalidated()
+ assertExecutorIsClear()
+ assertTrue(filter.shouldFilterOut(newerEntry, clock.uptimeMillis()))
+ }
+
+ @Test
+ fun testRetractedIsCanceled() {
+ // GIVEN A recently alerted target
+ addEntries(entry1HasRecentlyAlerted)
+ sendTargets(target1)
+
+ // WHEN the entry is removed
+ removeEntries(entry1HasRecentlyAlerted)
+
+ // THEN its pending timeout is canceled
+ assertExecutorIsClear()
+ clock.advanceTime(ALERT_WINDOW)
+ verifyPipelinesNotInvalidated()
+ }
+
+ @Test
+ fun testTargetBeforeEntryFunctionsProperly() {
+ // WHEN targets are added before their entries exist
+ sendTargets(target2, target1)
+
+ // THEN neither is filtered out
+ assertFalse(filter.shouldFilterOut(entry2HasNotRecentlyAlerted, now))
+ assertFalse(filter.shouldFilterOut(entry1HasRecentlyAlerted, now))
+
+ // WHEN the entries are later added
+ addEntries(entry2HasNotRecentlyAlerted, entry1HasRecentlyAlerted)
+
+ // THEN the pipelines are not invalidated (because they're already going to be rerun)
+ // but the first entry is still filtered out properly.
+ verifyPipelinesNotInvalidated()
+ assertTrue(filter.shouldFilterOut(entry2HasNotRecentlyAlerted, now))
+ }
+
+ @Test
+ fun testLockscreenTracking() {
+ // GIVEN a couple of smartspace targets that haven't alerted recently
+ addEntries(entry2HasNotRecentlyAlerted, entry4HasNotRecentlyAlerted)
+ sendTargets(target2, target4)
+ clearPipelineInvocations()
+
+ assertTrue(filter.shouldFilterOut(entry2HasNotRecentlyAlerted, now))
+
+ // WHEN we are no longer on the keyguard
+ statusBarListener.onStateChanged(StatusBarState.SHADE)
+
+ // THEN the new pipeline is invalidated (but the old one isn't because it's not
+ // necessary) because the notif should no longer be filtered out
+ verify(pluggableListener).onPluggableInvalidated(filter)
+ verify(notificationEntryManager, never()).updateNotifications(anyString())
+ assertFalse(filter.shouldFilterOut(entry2HasNotRecentlyAlerted, now))
+ }
+
+ private fun buildTargetFor(entry: NotificationEntry): SmartspaceTarget {
+ return SmartspaceTarget
+ .Builder("test", ComponentName("test", "class"), UserHandle.CURRENT)
+ .setSourceNotificationKey(entry.key)
+ .build()
+ }
+
+ private fun addEntries(vararg entries: NotificationEntry) {
+ for (entry in entries) {
+ `when`(notifPipeline.getEntry(entry.key)).thenReturn(entry)
+ collectionListener.onEntryAdded(entry)
+ }
+ }
+
+ private fun updateEntries(vararg entries: NotificationEntry) {
+ for (entry in entries) {
+ `when`(notifPipeline.getEntry(entry.key)).thenReturn(entry)
+ collectionListener.onEntryUpdated(entry)
+ }
+ }
+
+ private fun removeEntries(vararg entries: NotificationEntry) {
+ for (entry in entries) {
+ `when`(notifPipeline.getEntry(entry.key)).thenReturn(null)
+ collectionListener.onEntryRemoved(entry, 0)
+ }
+ }
+
+ private fun sendTargets(vararg targets: SmartspaceTarget) {
+ newTargetListener.onSmartspaceTargetsUpdated(targets.toMutableList())
+ }
+
+ private fun verifyPipelinesInvalidated() {
+ verify(pluggableListener).onPluggableInvalidated(filter)
+ verify(notificationEntryManager).updateNotifications(anyString())
+ }
+
+ private fun assertExecutorIsClear() {
+ assertEquals(0, executor.numPending())
+ }
+
+ private fun verifyPipelinesNotInvalidated() {
+ verify(pluggableListener, never()).onPluggableInvalidated(filter)
+ verify(notificationEntryManager, never()).updateNotifications(anyString())
+ }
+
+ private fun clearPipelineInvocations() {
+ clearInvocations(pluggableListener)
+ clearInvocations(notificationEntryManager)
+ }
+}
+
+private val ALERT_WINDOW = TimeUnit.SECONDS.toMillis(30)
+private const val PACKAGE_1 = "com.test.package.1"
+private const val PACKAGE_2 = "com.test.package.2"
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java
index 7b0c067..cea49b7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java
@@ -181,16 +181,6 @@
mEntryManager = new NotificationEntryManager(
mock(NotificationEntryManagerLogger.class),
mGroupMembershipManager,
- () -> new NotificationRankingManager(
- () -> mock(NotificationMediaManager.class),
- mGroupMembershipManager,
- mHeadsUpManager,
- mock(NotificationFilter.class),
- mock(NotificationEntryManagerLogger.class),
- mock(NotificationSectionsFeatureManager.class),
- mock(PeopleNotificationIdentifier.class),
- mock(HighPriorityProvider.class)),
- mEnvironment,
mFeatureFlags,
() -> mRowBinder,
() -> mRemoteInputManager,
@@ -198,6 +188,17 @@
mock(ForegroundServiceDismissalFeatureController.class),
mock(IStatusBarService.class)
);
+ mEntryManager.setRanker(
+ new NotificationRankingManager(
+ () -> mock(NotificationMediaManager.class),
+ mGroupMembershipManager,
+ mHeadsUpManager,
+ mock(NotificationFilter.class),
+ mock(NotificationEntryManagerLogger.class),
+ mock(NotificationSectionsFeatureManager.class),
+ mock(PeopleNotificationIdentifier.class),
+ mock(HighPriorityProvider.class),
+ mEnvironment));
NotifRemoteViewCache cache = new NotifRemoteViewCacheImpl(mEntryManager);
NotifBindPipeline pipeline = new NotifBindPipeline(
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 84fb368..8758e16 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
@@ -142,7 +142,6 @@
mNotificationSectionsManager,
mGroupMembershipManger,
mGroupExpansionManager,
- mStatusBarStateController,
mAmbientState,
mFeatureFlags);
mStackScrollerInternal.initView(getContext(), mKeyguardBypassEnabledProvider,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollerControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollerControllerTest.java
index 895339f..f376e88 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollerControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollerControllerTest.java
@@ -50,6 +50,7 @@
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.OnMenuEventListener;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.FeatureFlags;
+import com.android.systemui.statusbar.LockscreenShadeTransitionController;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationLockscreenUserManager.UserChangedListener;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
@@ -121,6 +122,7 @@
@Mock private NotificationEntryManager mEntryManager;
@Mock private IStatusBarService mIStatusBarService;
@Mock private UiEventLogger mUiEventLogger;
+ @Mock private LockscreenShadeTransitionController mLockscreenShadeTransitionController;
@Mock private ForegroundServiceDismissalFeatureController mFgFeatureController;
@Mock private ForegroundServiceSectionController mFgServicesSectionController;
@Mock private ForegroundServiceDungeonView mForegroundServiceDungeonView;
@@ -173,6 +175,7 @@
mNotifPipeline,
mNotifCollection,
mEntryManager,
+ mLockscreenShadeTransitionController,
mIStatusBarService,
mUiEventLogger,
mFgFeatureController,
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 45761df..6b4797f 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.statusbar.CommandQueue;
import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.KeyguardAffordanceView;
+import com.android.systemui.statusbar.LockscreenShadeTransitionController;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationShadeDepthController;
import com.android.systemui.statusbar.NotificationShelfController;
@@ -102,6 +103,7 @@
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.concurrency.FakeExecutor;
+import com.android.systemui.util.settings.SecureSettings;
import com.android.systemui.util.time.FakeSystemClock;
import com.android.wm.shell.animation.FlingAnimationUtils;
@@ -225,6 +227,8 @@
@Mock
private NotificationShadeDepthController mNotificationShadeDepthController;
@Mock
+ private LockscreenShadeTransitionController mLockscreenShadeTransitionController;
+ @Mock
private AuthController mAuthController;
@Mock
private ScrimController mScrimController;
@@ -246,6 +250,8 @@
private KeyguardMediaController mKeyguardMediaController;
@Mock
private PrivacyDotViewController mPrivacyDotViewController;
+ @Mock
+ private SecureSettings mSecureSettings;
private SysuiStatusBarStateController mStatusBarStateController;
private NotificationPanelViewController mNotificationPanelViewController;
@@ -311,7 +317,9 @@
mKeyguardBypassController, mHeadsUpManager,
mock(NotificationRoundnessManager.class),
mStatusBarStateController,
- new FalsingManagerFake(), new FalsingCollectorFake());
+ new FalsingManagerFake(),
+ mLockscreenShadeTransitionController,
+ new FalsingCollectorFake());
when(mKeyguardStatusViewComponentFactory.build(any()))
.thenReturn(mKeyguardStatusViewComponent);
when(mKeyguardStatusViewComponent.getKeyguardClockSwitchController())
@@ -327,7 +335,7 @@
mResources,
mLayoutInflater,
coordinator, expansionHandler, mDynamicPrivacyController, mKeyguardBypassController,
- new FalsingManagerFake(), new FalsingCollectorFake(), mShadeController,
+ new FalsingManagerFake(), new FalsingCollectorFake(),
mNotificationLockscreenUserManager, mNotificationEntryManager,
mKeyguardStateController, mStatusBarStateController, mDozeLog,
mDozeParameters, mCommandQueue, mVibratorHelper,
@@ -341,6 +349,7 @@
mKeyguardQsUserSwitchComponentFactory,
mKeyguardUserSwitcherComponentFactory,
mKeyguardStatusBarViewComponentFactory,
+ mLockscreenShadeTransitionController,
mQSDetailDisplayer,
mGroupManager,
mNotificationAreaController,
@@ -355,7 +364,8 @@
mQuickAccessWalletClient,
mKeyguardMediaController,
mPrivacyDotViewController,
- new FakeExecutor(new FakeSystemClock()));
+ new FakeExecutor(new FakeSystemClock()),
+ mSecureSettings);
mNotificationPanelViewController.initDependencies(
mStatusBar,
mNotificationShelfController);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewTest.java
index 0a3eec4d..6c1a3c9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewTest.java
@@ -31,12 +31,12 @@
import com.android.systemui.SystemUIFactory;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.classifier.FalsingCollectorFake;
-import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.dock.DockManager;
import com.android.systemui.doze.DozeLog;
import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.DragDownHelper;
+import com.android.systemui.statusbar.LockscreenShadeTransitionController;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationShadeDepthController;
import com.android.systemui.statusbar.NotificationShadeWindowController;
@@ -89,6 +89,7 @@
@Mock private NotificationShadeWindowController mNotificationShadeWindowController;
@Mock private NotificationStackScrollLayoutController mNotificationStackScrollLayoutController;
@Mock private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
+ @Mock private LockscreenShadeTransitionController mLockscreenShadeTransitionController;
@Before
public void setUp() {
@@ -112,7 +113,7 @@
mPulseExpansionHandler,
mDynamicPrivacyController,
mBypassController,
- new FalsingManagerFake(),
+ mLockscreenShadeTransitionController,
new FalsingCollectorFake(),
mPluginManager,
mTunerService,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
index f98f00c..a431a78 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
@@ -41,6 +41,7 @@
import android.os.Handler;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import android.util.MathUtils;
import android.view.View;
import androidx.test.filters.SmallTest;
@@ -1121,6 +1122,32 @@
assertAlphaAfterExpansion(mNotificationsScrim, /* alpha */ 0.8f, /* expansion */ 0.2f);
}
+ @Test
+ public void testNotificationTransparency_followsTransitionToFullShade() {
+ mScrimController.transitionTo(ScrimState.SHADE_LOCKED);
+ mScrimController.setPanelExpansion(1.0f);
+ finishAnimationsImmediately();
+ float shadeLockedAlpha = mNotificationsScrim.getViewAlpha();
+ mScrimController.transitionTo(ScrimState.KEYGUARD);
+ mScrimController.setPanelExpansion(1.0f);
+ finishAnimationsImmediately();
+ float keyguardAlpha = mNotificationsScrim.getViewAlpha();
+
+ mScrimController.setClipsQsScrim(true);
+ float progress = 0.5f;
+ mScrimController.setTransitionToFullShadeProgress(progress);
+ assertEquals(MathUtils.lerp(keyguardAlpha, shadeLockedAlpha, progress),
+ mNotificationsScrim.getViewAlpha(), 0.2);
+ progress = 0.0f;
+ mScrimController.setTransitionToFullShadeProgress(progress);
+ assertEquals(MathUtils.lerp(keyguardAlpha, shadeLockedAlpha, progress),
+ mNotificationsScrim.getViewAlpha(), 0.2);
+ progress = 1.0f;
+ mScrimController.setTransitionToFullShadeProgress(progress);
+ assertEquals(MathUtils.lerp(keyguardAlpha, shadeLockedAlpha, progress),
+ mNotificationsScrim.getViewAlpha(), 0.2);
+ }
+
private void assertAlphaAfterExpansion(ScrimView scrim, float expectedAlpha, float expansion) {
mScrimController.setPanelExpansion(expansion);
finishAnimationsImmediately();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
index 8601de5..ce45f26 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
@@ -40,6 +40,7 @@
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.KeyguardIndicationController;
+import com.android.systemui.statusbar.LockscreenShadeTransitionController;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
@@ -127,7 +128,8 @@
mock(NotificationShadeWindowController.class), mock(DynamicPrivacyController.class),
mock(KeyguardStateController.class),
mock(KeyguardIndicationController.class), mStatusBar,
- mock(ShadeControllerImpl.class), mCommandQueue, mInitController,
+ mock(ShadeControllerImpl.class), mock(LockscreenShadeTransitionController.class),
+ mCommandQueue, mInitController,
mNotificationInterruptStateProvider);
mInitController.executePostInitTasks();
ArgumentCaptor<NotificationInterruptSuppressor> suppressorCaptor =
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 b3d52b8..5a3683e 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
@@ -101,6 +101,7 @@
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.KeyguardIndicationController;
+import com.android.systemui.statusbar.LockscreenShadeTransitionController;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationMediaManager;
@@ -267,6 +268,7 @@
@Mock private OngoingCallController mOngoingCallController;
@Mock private SystemStatusAnimationScheduler mAnimationScheduler;
@Mock private StatusBarLocationPublisher mLocationPublisher;
+ @Mock private LockscreenShadeTransitionController mLockscreenTransitionController;
@Mock private FeatureFlags mFeatureFlags;
@Mock private IWallpaperManager mWallpaperManager;
@Mock private KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
@@ -437,6 +439,7 @@
mOngoingCallController,
mAnimationScheduler,
mLocationPublisher,
+ mLockscreenTransitionController,
mFeatureFlags,
mKeyguardUnlockAnimationController);
when(mKeyguardViewMediator.registerStatusBar(any(StatusBar.class), any(ViewGroup.class),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallChronometerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallChronometerTest.kt
index 0e77bb3..e32af60 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallChronometerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallChronometerTest.kt
@@ -20,7 +20,6 @@
import android.testing.TestableLooper
import android.view.LayoutInflater
import android.view.View
-import android.widget.LinearLayout
import androidx.test.filters.SmallTest
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
@@ -48,8 +47,7 @@
fun setUp() {
allowTestableLooperAsMainThread()
TestableLooper.get(this).runWithLooper {
- val chipView = LayoutInflater.from(mContext)
- .inflate(R.layout.ongoing_call_chip, null) as LinearLayout
+ val chipView = LayoutInflater.from(mContext).inflate(R.layout.ongoing_call_chip, null)
textView = chipView.findViewById(R.id.ongoing_call_chip_time)!!
measureTextView()
calculateDoesNotFixText()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt
index 9a7ab28..3a71ecf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt
@@ -27,6 +27,7 @@
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import android.view.LayoutInflater
+import android.view.View
import android.widget.LinearLayout
import androidx.test.filters.SmallTest
import com.android.internal.logging.testing.UiEventLoggerFake
@@ -80,14 +81,13 @@
@Mock private lateinit var mockActivityStarter: ActivityStarter
@Mock private lateinit var mockIActivityManager: IActivityManager
- private lateinit var chipView: LinearLayout
+ private lateinit var chipView: View
@Before
fun setUp() {
allowTestableLooperAsMainThread()
TestableLooper.get(this).runWithLooper {
- chipView = LayoutInflater.from(mContext)
- .inflate(R.layout.ongoing_call_chip, null) as LinearLayout
+ chipView = LayoutInflater.from(mContext).inflate(R.layout.ongoing_call_chip, null)
}
MockitoAnnotations.initMocks(this)
@@ -116,7 +116,7 @@
}
@Test
- fun onEntryUpdated_isOngoingCallNotif_listenerNotifiedWithRightCallTime() {
+ fun onEntryUpdated_isOngoingCallNotif_listenerNotified() {
notifCollectionListener.onEntryUpdated(createOngoingCallNotifEntry())
verify(mockOngoingCallListener).onOngoingCallStateChanged(anyBoolean())
@@ -130,6 +130,15 @@
}
@Test
+ fun onEntryUpdated_ongoingCallNotifThenScreeningCallNotif_listenerNotifiedTwice() {
+ notifCollectionListener.onEntryUpdated(createOngoingCallNotifEntry())
+ notifCollectionListener.onEntryUpdated(createScreeningCallNotifEntry())
+
+ verify(mockOngoingCallListener, times(2))
+ .onOngoingCallStateChanged(anyBoolean())
+ }
+
+ @Test
fun onEntryRemoved_ongoingCallNotif_listenerNotified() {
notifCollectionListener.onEntryRemoved(createOngoingCallNotifEntry(), REASON_USER_STOPPED)
@@ -188,6 +197,22 @@
assertThat(controller.hasOngoingCall()).isFalse()
}
+ @Test
+ fun hasOngoingCall_ongoingCallNotifSentThenScreeningCallNotifSent_returnsFalse() {
+ notifCollectionListener.onEntryUpdated(createOngoingCallNotifEntry())
+ notifCollectionListener.onEntryUpdated(createScreeningCallNotifEntry())
+
+ assertThat(controller.hasOngoingCall()).isFalse()
+ }
+
+ @Test
+ fun hasOngoingCall_ongoingCallNotifSentThenUnrelatedNotifSent_returnsTrue() {
+ notifCollectionListener.onEntryUpdated(createOngoingCallNotifEntry())
+ notifCollectionListener.onEntryUpdated(createNotCallNotifEntry())
+
+ assertThat(controller.hasOngoingCall()).isTrue()
+ }
+
/**
* This test fakes a theme change during an ongoing call.
*
@@ -200,10 +225,9 @@
// Start an ongoing call.
notifCollectionListener.onEntryUpdated(createOngoingCallNotifEntry())
- lateinit var newChipView: LinearLayout
+ lateinit var newChipView: View
TestableLooper.get(this).runWithLooper {
- newChipView = LayoutInflater.from(mContext)
- .inflate(R.layout.ongoing_call_chip, null) as LinearLayout
+ newChipView = LayoutInflater.from(mContext).inflate(R.layout.ongoing_call_chip, null)
}
// Change the chip view associated with the controller.
@@ -281,9 +305,13 @@
// Other tests for notifyChipVisibilityChanged are in [OngoingCallLogger], since
// [OngoingCallController.notifyChipVisibilityChanged] just delegates to that class.
- private fun createOngoingCallNotifEntry(): NotificationEntry {
+ private fun createOngoingCallNotifEntry() = createCallNotifEntry(ongoingCallStyle)
+
+ private fun createScreeningCallNotifEntry() = createCallNotifEntry(screeningCallStyle)
+
+ private fun createCallNotifEntry(callStyle: Notification.CallStyle): NotificationEntry {
val notificationEntryBuilder = NotificationEntryBuilder()
- notificationEntryBuilder.modifyNotification(context).style = ongoingCallStyle
+ notificationEntryBuilder.modifyNotification(context).style = callStyle
val contentIntent = mock(PendingIntent::class.java)
`when`(contentIntent.intent).thenReturn(mock(Intent::class.java))
@@ -295,6 +323,9 @@
private fun createNotCallNotifEntry() = NotificationEntryBuilder().build()
}
-private val ongoingCallStyle = Notification.CallStyle.forOngoingCall(
- Person.Builder().setName("name").build(),
- /* hangUpIntent= */ mock(PendingIntent::class.java))
+private val person = Person.Builder().setName("name").build()
+private val hangUpIntent = mock(PendingIntent::class.java)
+
+private val ongoingCallStyle = Notification.CallStyle.forOngoingCall(person, hangUpIntent)
+private val screeningCallStyle = Notification.CallStyle.forScreeningCall(
+ person, hangUpIntent, /* answerIntent= */ mock(PendingIntent::class.java))
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
index 687ca60..521b958 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
@@ -43,6 +43,7 @@
public void setUp() throws Exception {
super.setUp();
when(mWifiInfo.makeCopy(anyLong())).thenReturn(mWifiInfo);
+ when(mWifiInfo.isPrimary()).thenReturn(true);
}
@Test
@@ -277,6 +278,20 @@
}
}
+ @Test
+ public void testNonPrimaryWiFi() {
+ String testSsid = "Test SSID";
+ setWifiEnabled(true);
+ setWifiState(true, testSsid);
+ // Set the ImsType to be IMS_TYPE_WLAN
+ setImsType(2);
+ setWifiLevel(1);
+ verifyLastCallStrength(TelephonyIcons.WIFI_CALL_STRENGTH_ICONS[1]);
+ when(mWifiInfo.isPrimary()).thenReturn(false);
+ setWifiLevel(3);
+ verifyLastCallStrength(TelephonyIcons.WIFI_CALL_STRENGTH_ICONS[1]);
+ }
+
protected void setWifiActivity(int activity) {
// TODO: Not this, because this variable probably isn't sticking around.
mNetworkController.mWifiSignalController.setActivity(activity);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wallet/ui/WalletScreenControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/wallet/ui/WalletScreenControllerTest.java
index ac5da17..cd1eb1c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wallet/ui/WalletScreenControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wallet/ui/WalletScreenControllerTest.java
@@ -182,6 +182,80 @@
}
@Test
+ public void queryCards_hasCards_showCarousel_badCard_parseLabel_notCrash() {
+ GetWalletCardsResponse response =
+ new GetWalletCardsResponse(
+ Collections.singletonList(createCrazyWalletCard(mContext, true)), 0);
+
+ mController.queryWalletCards();
+ mTestableLooper.processAllMessages();
+
+ verify(mWalletClient).getWalletCards(any(), any(), mCallbackCaptor.capture());
+
+ QuickAccessWalletClient.OnWalletCardsRetrievedCallback callback =
+ mCallbackCaptor.getValue();
+
+ assertEquals(mController, callback);
+
+ callback.onWalletCardsRetrieved(response);
+ mTestableLooper.processAllMessages();
+
+ assertEquals(VISIBLE, mWalletView.getCardCarouselContainer().getVisibility());
+ assertEquals("This\nis\ncrazy!!", mWalletView.getCardLabel().getText().toString());
+ assertEquals(GONE, mWalletView.getActionButton().getVisibility());
+ assertEquals(GONE, mWalletView.getErrorView().getVisibility());
+ }
+
+ @Test
+ public void queryCards_hasCards_showCarousel_badCard_noLabel_notCrash() {
+ GetWalletCardsResponse response =
+ new GetWalletCardsResponse(
+ Collections.singletonList(createCrazyWalletCard(mContext, false)), 0);
+
+ mController.queryWalletCards();
+ mTestableLooper.processAllMessages();
+
+ verify(mWalletClient).getWalletCards(any(), any(), mCallbackCaptor.capture());
+
+ QuickAccessWalletClient.OnWalletCardsRetrievedCallback callback =
+ mCallbackCaptor.getValue();
+
+ assertEquals(mController, callback);
+
+ callback.onWalletCardsRetrieved(response);
+ mTestableLooper.processAllMessages();
+
+ assertEquals(VISIBLE, mWalletView.getCardCarouselContainer().getVisibility());
+ assertEquals("", mWalletView.getCardLabel().getText().toString());
+ assertEquals(GONE, mWalletView.getActionButton().getVisibility());
+ assertEquals(GONE, mWalletView.getErrorView().getVisibility());
+ }
+
+ @Test
+ public void queryCards_hasCards_showCarousel_invalidSelectedIndex_notCrash() {
+ GetWalletCardsResponse response =
+ new GetWalletCardsResponse(
+ Collections.singletonList(createCrazyWalletCard(mContext, true)), 8);
+
+ mController.queryWalletCards();
+ mTestableLooper.processAllMessages();
+
+ verify(mWalletClient).getWalletCards(any(), any(), mCallbackCaptor.capture());
+
+ QuickAccessWalletClient.OnWalletCardsRetrievedCallback callback =
+ mCallbackCaptor.getValue();
+
+ assertEquals(mController, callback);
+
+ callback.onWalletCardsRetrieved(response);
+ mTestableLooper.processAllMessages();
+
+ assertEquals(GONE, mWalletView.getCardCarouselContainer().getVisibility());
+ assertEquals(VISIBLE, mWalletView.getEmptyStateView().getVisibility());
+ assertEquals(GONE, mWalletView.getErrorView().getVisibility());
+ }
+
+ @Test
public void queryCards_noCards_showEmptyState() {
GetWalletCardsResponse response = new GetWalletCardsResponse(Collections.EMPTY_LIST, 0);
@@ -329,6 +403,15 @@
.build();
}
+ private WalletCard createCrazyWalletCard(Context context, boolean hasLabel) {
+ PendingIntent pendingIntent =
+ PendingIntent.getActivity(context, 0, mWalletIntent, PendingIntent.FLAG_IMMUTABLE);
+ return new WalletCard.Builder("BadCard", createIcon(), "•••• 1234", pendingIntent)
+ .setCardIcon(null)
+ .setCardLabel(hasLabel ? "This\nis\ncrazy!!" : null)
+ .build();
+ }
+
private static Icon createIcon() {
return Icon.createWithBitmap(Bitmap.createBitmap(70, 44, Bitmap.Config.ARGB_8888));
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java
index 79641db..1dd0b21 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java
@@ -37,7 +37,6 @@
import com.android.wm.shell.hidedisplaycutout.HideDisplayCutout;
import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import com.android.wm.shell.onehanded.OneHanded;
-import com.android.wm.shell.onehanded.OneHandedGestureHandler;
import com.android.wm.shell.onehanded.OneHandedTransitionCallback;
import com.android.wm.shell.pip.Pip;
@@ -106,11 +105,6 @@
verify(mKeyguardUpdateMonitor).registerCallback(any(KeyguardUpdateMonitorCallback.class));
verify(mCommandQueue).addCallback(any(CommandQueue.Callbacks.class));
verify(mScreenLifecycle).addObserver(any(ScreenLifecycle.Observer.class));
- verify(mNavigationModeController).addListener(
- any(NavigationModeController.ModeChangedListener.class));
-
- verify(mOneHanded).registerGestureCallback(any(
- OneHandedGestureHandler.OneHandedGestureEventCallback.class));
verify(mOneHanded).registerTransitionCallback(any(OneHandedTransitionCallback.class));
}
diff --git a/packages/VpnDialogs/res/values-af/strings.xml b/packages/VpnDialogs/res/values-af/strings.xml
index ac82b0e..88ccbd9 100644
--- a/packages/VpnDialogs/res/values-af/strings.xml
+++ b/packages/VpnDialogs/res/values-af/strings.xml
@@ -18,6 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Verbindingversoek"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> wil \'n VPN-verbinding opstel wat dit sal toelaat om netwerkverkeer te monitor. Aanvaar dit net as jy die bron vertrou. <br /> <br /> <img src=vpn_icon /> verskyn boaan jou skerm as VPN aktief is."</string>
+ <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> wil \'n VPN-verbinding opstel wat dit toelaat om netwerkverkeer te monitor. Aanvaar dit net as jy die bron vertrou. <br /> <br /> <img src=vpn_icon /> verskyn op jou skerm wanneer VPN aktief is."</string>
<string name="legacy_title" msgid="192936250066580964">"VPN is gekoppel"</string>
<string name="session" msgid="6470628549473641030">"Sessie:"</string>
<string name="duration" msgid="3584782459928719435">"Tydsduur:"</string>
diff --git a/packages/VpnDialogs/res/values-am/strings.xml b/packages/VpnDialogs/res/values-am/strings.xml
index ad9773b..9fc5ff4 100644
--- a/packages/VpnDialogs/res/values-am/strings.xml
+++ b/packages/VpnDialogs/res/values-am/strings.xml
@@ -18,6 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"የግንኙነት ጥያቄ"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> የአውታረ መረብ መከታተል የሚያስችል የVPN ግንኑነት ማዋቀር ይፈልጋል። ምንጩን የሚያምኑት ብቻ ከሆኑ ይቀበሉ። <br /> <br /> <img src=vpn_icon /> VPN ገቢር ሲሆን በማያ ገጽዎ ላይኛው ክፍል ላይ ይታያል።"</string>
+ <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> የአውታረ መረብ ትራፊክን ለመቆጣጠር የሚያስችል የVPN ግንኙነትን ማዋቀር ይፈልጋል። ምንጩን የሚያምኑ ከሆነ ብቻ ይቀበሉ። <br /> <br /> <img src=vpn_icon /> ማያ ገጹ ላይ VPN ገቢር ሲሆን ይታያል።"</string>
<string name="legacy_title" msgid="192936250066580964">"VPN ተያይዟል"</string>
<string name="session" msgid="6470628549473641030">"ክፍለ ጊዜ፡"</string>
<string name="duration" msgid="3584782459928719435">"ጊዜ"</string>
diff --git a/packages/VpnDialogs/res/values-ar/strings.xml b/packages/VpnDialogs/res/values-ar/strings.xml
index 808cde9..b99d761 100644
--- a/packages/VpnDialogs/res/values-ar/strings.xml
+++ b/packages/VpnDialogs/res/values-ar/strings.xml
@@ -18,6 +18,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"طلب الاتصال"</string>
<string name="warning" msgid="809658604548412033">"يريد <xliff:g id="APP">%s</xliff:g> إعداد الاتصال بالشبكة الافتراضية الخاصة التي تتيح له مراقبة حركة المرور على الشبكة. فلا توافق إلا إذا كنت تثق في المصدر. <br /> <br /> <img src=vpn_icon /> يظهر في الجزء العلوي من الشاشة عندما تكون الشبكة الافتراضية الخاصة نشطة."</string>
+ <!-- no translation found for warning (5188957997628124947) -->
+ <skip />
<string name="legacy_title" msgid="192936250066580964">"VPN متصلة"</string>
<string name="session" msgid="6470628549473641030">"الجلسة"</string>
<string name="duration" msgid="3584782459928719435">"المدة:"</string>
diff --git a/packages/VpnDialogs/res/values-as/strings.xml b/packages/VpnDialogs/res/values-as/strings.xml
index 45d8458..ad404cf 100644
--- a/packages/VpnDialogs/res/values-as/strings.xml
+++ b/packages/VpnDialogs/res/values-as/strings.xml
@@ -18,6 +18,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"সংযোগৰ অনুৰোধ"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g>এ নেটৱৰ্ক ট্ৰেফিক নিৰীক্ষণ কৰিবলৈ এটা ভিপিএন সংযোগ ছেট আপ কৰিবলৈ বিচাৰিছে৷ আপুনি কেৱল উৎসটোক বিশ্বাস কৰিলেহে অনুৰোধ স্বীকাৰ কৰিব৷ ভিপিএন সক্ৰিয় থকাৰ সময়ত আপোনাৰ স্ক্ৰীণৰ ওপৰত <br /> <br /> <img src=vpn_icon /> দৃশ্যমান হয়৷"</string>
+ <!-- no translation found for warning (5188957997628124947) -->
+ <skip />
<string name="legacy_title" msgid="192936250066580964">"ভিপিএন সংযোগ হৈ আছে"</string>
<string name="session" msgid="6470628549473641030">"ছেশ্বন:"</string>
<string name="duration" msgid="3584782459928719435">"সময়সীমা:"</string>
diff --git a/packages/VpnDialogs/res/values-az/strings.xml b/packages/VpnDialogs/res/values-az/strings.xml
index 2bdf23e..09428b8 100644
--- a/packages/VpnDialogs/res/values-az/strings.xml
+++ b/packages/VpnDialogs/res/values-az/strings.xml
@@ -18,6 +18,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Bağlantı Sorğusu"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> VPN bağlantı yaratmaq istəyir ki, bu da şəbəkə trafikini izləyə bilər. Yalnız mənbəyə güvəndiyiniz halda qəbul edin. VPN aktiv olan zaman <br /> <br /> <img src=vpn_icon /> ekranın yuxarısında görünür."</string>
+ <!-- no translation found for warning (5188957997628124947) -->
+ <skip />
<string name="legacy_title" msgid="192936250066580964">"VPN qoşuludur"</string>
<string name="session" msgid="6470628549473641030">"Sessiya:"</string>
<string name="duration" msgid="3584782459928719435">"Müddət:"</string>
diff --git a/packages/VpnDialogs/res/values-b+sr+Latn/strings.xml b/packages/VpnDialogs/res/values-b+sr+Latn/strings.xml
index f40e406..a1075d2 100644
--- a/packages/VpnDialogs/res/values-b+sr+Latn/strings.xml
+++ b/packages/VpnDialogs/res/values-b+sr+Latn/strings.xml
@@ -18,6 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Zahtev za povezivanje"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> želi da podesi VPN vezu koja omogućava praćenje saobraćaja na mreži. Prihvatite samo ako verujete izvoru. <br /> <br /> <img src=vpn_icon /> se prikazuje u vrhu ekrana kada je VPN aktivan."</string>
+ <string name="warning" product="tv" msgid="5188957997628124947">"Aplikacija <xliff:g id="APP">%s</xliff:g> želi da podesi VPN vezu koja joj omogućava da prati mrežni saobraćaj. Prihvatite ovo samo ako imate poverenja u izvor. <br /> <br /> <img src=vpn_icon /> se prikazuje na ekranu kada je VPN aktivan."</string>
<string name="legacy_title" msgid="192936250066580964">"VPN je povezan"</string>
<string name="session" msgid="6470628549473641030">"Sesija:"</string>
<string name="duration" msgid="3584782459928719435">"Trajanje:"</string>
diff --git a/packages/VpnDialogs/res/values-be/strings.xml b/packages/VpnDialogs/res/values-be/strings.xml
index 0903c8e..88e6a61 100644
--- a/packages/VpnDialogs/res/values-be/strings.xml
+++ b/packages/VpnDialogs/res/values-be/strings.xml
@@ -18,6 +18,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Запыт на падлучэнне"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> спрабуе наладзіць падлучэнне VPN, якое дазваляе сачыць за сеткавым трафікам. Прымайце толькі тады, калі вы давяраеце гэтай крыніцы. Калі VPN актыўны, у верхняй частцы экрана адлюстроўваецца <br /> <br /> <img src=vpn_icon />."</string>
+ <!-- no translation found for warning (5188957997628124947) -->
+ <skip />
<string name="legacy_title" msgid="192936250066580964">"VPN падключаны"</string>
<string name="session" msgid="6470628549473641030">"Сессія"</string>
<string name="duration" msgid="3584782459928719435">"Працягласць:"</string>
diff --git a/packages/VpnDialogs/res/values-bg/strings.xml b/packages/VpnDialogs/res/values-bg/strings.xml
index 9ac853d..6345f1d 100644
--- a/packages/VpnDialogs/res/values-bg/strings.xml
+++ b/packages/VpnDialogs/res/values-bg/strings.xml
@@ -18,6 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Заявка за свързване"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> иска да настрои връзка с виртуална частна мрежа (VPN), за да може да наблюдава мрежовия трафик. Приемете само ако източникът е надежден. Иконата <br /> <br /> <img src=vpn_icon /> се показва в долната част на екрана при активирана VPN."</string>
+ <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> иска да настрои връзка с VPN, за да може да наблюдава трафика в мрежата. Приемете само ако източникът е надежден. <br /> <br /> <img src=vpn_icon /> се показва на екрана при активирана VPN."</string>
<string name="legacy_title" msgid="192936250066580964">"VPN е свързана"</string>
<string name="session" msgid="6470628549473641030">"Сесия:"</string>
<string name="duration" msgid="3584782459928719435">"Продължителност:"</string>
diff --git a/packages/VpnDialogs/res/values-bn/strings.xml b/packages/VpnDialogs/res/values-bn/strings.xml
index 5e11fd9..041e46c 100644
--- a/packages/VpnDialogs/res/values-bn/strings.xml
+++ b/packages/VpnDialogs/res/values-bn/strings.xml
@@ -18,6 +18,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"সংযোগের অনুরোধ"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> এমন একটি VPN সংযোগ সেট-আপ করতে চাচ্ছে যেটি দিয়ে এটি নেটওয়ার্ক ট্রাফিক নিরীক্ষণ করতে পারবে। আপনি যদি উৎসটিকে বিশ্বাস করেন, তাহলেই কেবল এতে সম্মতি দিন। VPN সক্রিয় থাকলে আপনার স্ক্রীনের উপরে <br /> <br /> <img src=vpn_icon /> দেখা যাবে।"</string>
+ <!-- no translation found for warning (5188957997628124947) -->
+ <skip />
<string name="legacy_title" msgid="192936250066580964">"VPN সংযুক্ত হয়েছে"</string>
<string name="session" msgid="6470628549473641030">"অধিবেশন:"</string>
<string name="duration" msgid="3584782459928719435">"সময়কাল:"</string>
diff --git a/packages/VpnDialogs/res/values-bs/strings.xml b/packages/VpnDialogs/res/values-bs/strings.xml
index 56812d5..fa5f4ea 100644
--- a/packages/VpnDialogs/res/values-bs/strings.xml
+++ b/packages/VpnDialogs/res/values-bs/strings.xml
@@ -18,6 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Zahtjev za povezivanje"</string>
<string name="warning" msgid="809658604548412033">"Aplikacija <xliff:g id="APP">%s</xliff:g> želi podesiti VPN vezu koja joj omogućava praćenje mrežnog saobraćaja. Prihvatite samo ako je izvor pouzdan. <br /> <br /> <img src=vpn_icon /> se pojavi na vrhu ekrana kada je VPN aktivna."</string>
+ <string name="warning" product="tv" msgid="5188957997628124947">"Aplikacija <xliff:g id="APP">%s</xliff:g> želi postaviti VPN vezu koja joj omogućava praćenje mrežnog saobraćaja. Prihvatite samo ako vjerujete izvoru. Kada je VPN aktivan, na ekranu se prikazuje ikona <br /> <br /> <img src=vpn_icon />."</string>
<string name="legacy_title" msgid="192936250066580964">"VPN veza uspostavljena"</string>
<string name="session" msgid="6470628549473641030">"Sesija:"</string>
<string name="duration" msgid="3584782459928719435">"Trajanje:"</string>
diff --git a/packages/VpnDialogs/res/values-ca/strings.xml b/packages/VpnDialogs/res/values-ca/strings.xml
index 97738c3..7674c2c 100644
--- a/packages/VpnDialogs/res/values-ca/strings.xml
+++ b/packages/VpnDialogs/res/values-ca/strings.xml
@@ -18,6 +18,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Sol·licitud de connexió"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> vol configurar una connexió VPN que li permeti controlar el trànsit de xarxa. Accepta la sol·licitud només si prové d\'una font de confiança. <br /> <br /> <img src=vpn_icon /> es mostra a la part superior de la pantalla quan la VPN està activada."</string>
+ <!-- no translation found for warning (5188957997628124947) -->
+ <skip />
<string name="legacy_title" msgid="192936250066580964">"La VPN està connectada"</string>
<string name="session" msgid="6470628549473641030">"Sessió:"</string>
<string name="duration" msgid="3584782459928719435">"Durada:"</string>
diff --git a/packages/VpnDialogs/res/values-cs/strings.xml b/packages/VpnDialogs/res/values-cs/strings.xml
index 5cc809c..c06f6ff 100644
--- a/packages/VpnDialogs/res/values-cs/strings.xml
+++ b/packages/VpnDialogs/res/values-cs/strings.xml
@@ -18,6 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Žádost o připojení"</string>
<string name="warning" msgid="809658604548412033">"Aplikace <xliff:g id="APP">%s</xliff:g> žádá o nastavení připojení VPN, pomocí kterého bude moci sledovat síťový provoz. Povolte, jen pokud zdroji důvěřujete. <br /> <br /> <img src=vpn_icon /> – když je síť VPN aktivní, v horní části obrazovky se zobrazuje tato ikona."</string>
+ <string name="warning" product="tv" msgid="5188957997628124947">"Aplikace <xliff:g id="APP">%s</xliff:g> chce nastavit připojení VPN, které umožňuje sledovat síťový provoz. Povolte, jen pokud zdroji důvěřujete. <br /> <br /> <img src=vpn_icon /> – když je síť VPN aktivní, na obrazovce se zobrazuje tato ikona."</string>
<string name="legacy_title" msgid="192936250066580964">"Síť VPN je připojena"</string>
<string name="session" msgid="6470628549473641030">"Relace:"</string>
<string name="duration" msgid="3584782459928719435">"Doba trvání:"</string>
diff --git a/packages/VpnDialogs/res/values-da/strings.xml b/packages/VpnDialogs/res/values-da/strings.xml
index 7641158..a4ddc19 100644
--- a/packages/VpnDialogs/res/values-da/strings.xml
+++ b/packages/VpnDialogs/res/values-da/strings.xml
@@ -18,6 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Forbindelsesanmodning"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> vil konfigurere en VPN-forbindelse, der giver appen mulighed for at registrere netværkstrafik. Du bør kun acceptere dette, hvis du har tillid til kilden. <br /> <br /> <img src=vpn_icon /> vises øverst på din skærm, når VPN-forbindelsen er aktiv."</string>
+ <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> anmoder om at konfigurere en VPN-forbindelse, der giver appen tilladelse til at holde øje med netværkstrafik. Du bør kun acceptere dette, hvis du har tillid til appen. <br /> <br /> <img src=vpn_icon /> vises på din skærm, når VPN-forbindelsen er aktiv."</string>
<string name="legacy_title" msgid="192936250066580964">"VPN er tilsluttet"</string>
<string name="session" msgid="6470628549473641030">"Session:"</string>
<string name="duration" msgid="3584782459928719435">"Varighed:"</string>
diff --git a/packages/VpnDialogs/res/values-de/strings.xml b/packages/VpnDialogs/res/values-de/strings.xml
index 0f1e009..f38e395 100644
--- a/packages/VpnDialogs/res/values-de/strings.xml
+++ b/packages/VpnDialogs/res/values-de/strings.xml
@@ -18,6 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Verbindungsanfrage"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> möchte eine VPN-Verbindung herstellen, über die der Netzwerkverkehr überwacht werden kann. Lass die Verbindung nur zu, wenn die App vertrauenswürdig ist. Wenn VPN aktiv ist, wird oben im Display <br /> <br /> <img src=vpn_icon /> angezeigt."</string>
+ <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> möchte eine VPN-Verbindung herstellen, über die der Netzwerkverkehr überwacht werden kann. Lass die Verbindung nur zu, wenn die App vertrauenswürdig ist. <br /> <br /> <img src=vpn_icon /> wird auf dem Display angezeigt, wenn VPN aktiv ist."</string>
<string name="legacy_title" msgid="192936250066580964">"VPN ist verbunden"</string>
<string name="session" msgid="6470628549473641030">"Sitzung:"</string>
<string name="duration" msgid="3584782459928719435">"Dauer:"</string>
diff --git a/packages/VpnDialogs/res/values-el/strings.xml b/packages/VpnDialogs/res/values-el/strings.xml
index 78bcc43..e3eb460 100644
--- a/packages/VpnDialogs/res/values-el/strings.xml
+++ b/packages/VpnDialogs/res/values-el/strings.xml
@@ -18,6 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Αίτημα σύνδεσης"</string>
<string name="warning" msgid="809658604548412033">"Η εφαρμογή <xliff:g id="APP">%s</xliff:g> επιθυμεί να ρυθμίσει μια σύνδεση VPN που της επιτρέπει να παρακολουθεί την επισκεψιμότητα του δικτύου. Αποδεχτείτε το αίτημα μόνο εάν εμπιστεύεστε την πηγή. Το εικονίδιο <br /> <br /> <img src=vpn_icon /> εμφανίζεται στο επάνω μέρος της οθόνης σας όταν είναι ενεργό το VPN."</string>
+ <string name="warning" product="tv" msgid="5188957997628124947">"Η εφαρμογή <xliff:g id="APP">%s</xliff:g> επιθυμεί να ρυθμίσει μια σύνδεση VPN που της επιτρέπει να παρακολουθεί την επισκεψιμότητα του δικτύου. Αποδεχτείτε το αίτημα μόνο εάν εμπιστεύεστε την πηγή. Το εικονίδιο <br /> <br /> <img src=vpn_icon /> εμφανίζεται στην οθόνη σας όταν είναι ενεργό το VPN."</string>
<string name="legacy_title" msgid="192936250066580964">"Το VPN συνδέθηκε"</string>
<string name="session" msgid="6470628549473641030">"Περίοδος σύνδεσης"</string>
<string name="duration" msgid="3584782459928719435">"Διάρκεια:"</string>
diff --git a/packages/VpnDialogs/res/values-en-rAU/strings.xml b/packages/VpnDialogs/res/values-en-rAU/strings.xml
index 6ed50a7..cb8b79d 100644
--- a/packages/VpnDialogs/res/values-en-rAU/strings.xml
+++ b/packages/VpnDialogs/res/values-en-rAU/strings.xml
@@ -18,6 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Connection request"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> wants to set up a VPN connection that allows it to monitor network traffic. Only accept if you trust the source. <br /> <br /> <img src=vpn_icon /> appears at the top of your screen when VPN is active."</string>
+ <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> wants to set up a VPN connection that allows it to monitor network traffic. Only accept if you trust the source. <br /> <br /> <img src=vpn_icon /> appears on your screen when VPN is active."</string>
<string name="legacy_title" msgid="192936250066580964">"VPN is connected"</string>
<string name="session" msgid="6470628549473641030">"Session:"</string>
<string name="duration" msgid="3584782459928719435">"Duration:"</string>
diff --git a/packages/VpnDialogs/res/values-en-rCA/strings.xml b/packages/VpnDialogs/res/values-en-rCA/strings.xml
index 6ed50a7..cb8b79d 100644
--- a/packages/VpnDialogs/res/values-en-rCA/strings.xml
+++ b/packages/VpnDialogs/res/values-en-rCA/strings.xml
@@ -18,6 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Connection request"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> wants to set up a VPN connection that allows it to monitor network traffic. Only accept if you trust the source. <br /> <br /> <img src=vpn_icon /> appears at the top of your screen when VPN is active."</string>
+ <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> wants to set up a VPN connection that allows it to monitor network traffic. Only accept if you trust the source. <br /> <br /> <img src=vpn_icon /> appears on your screen when VPN is active."</string>
<string name="legacy_title" msgid="192936250066580964">"VPN is connected"</string>
<string name="session" msgid="6470628549473641030">"Session:"</string>
<string name="duration" msgid="3584782459928719435">"Duration:"</string>
diff --git a/packages/VpnDialogs/res/values-en-rGB/strings.xml b/packages/VpnDialogs/res/values-en-rGB/strings.xml
index 6ed50a7..cb8b79d 100644
--- a/packages/VpnDialogs/res/values-en-rGB/strings.xml
+++ b/packages/VpnDialogs/res/values-en-rGB/strings.xml
@@ -18,6 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Connection request"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> wants to set up a VPN connection that allows it to monitor network traffic. Only accept if you trust the source. <br /> <br /> <img src=vpn_icon /> appears at the top of your screen when VPN is active."</string>
+ <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> wants to set up a VPN connection that allows it to monitor network traffic. Only accept if you trust the source. <br /> <br /> <img src=vpn_icon /> appears on your screen when VPN is active."</string>
<string name="legacy_title" msgid="192936250066580964">"VPN is connected"</string>
<string name="session" msgid="6470628549473641030">"Session:"</string>
<string name="duration" msgid="3584782459928719435">"Duration:"</string>
diff --git a/packages/VpnDialogs/res/values-en-rIN/strings.xml b/packages/VpnDialogs/res/values-en-rIN/strings.xml
index 6ed50a7..cb8b79d 100644
--- a/packages/VpnDialogs/res/values-en-rIN/strings.xml
+++ b/packages/VpnDialogs/res/values-en-rIN/strings.xml
@@ -18,6 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Connection request"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> wants to set up a VPN connection that allows it to monitor network traffic. Only accept if you trust the source. <br /> <br /> <img src=vpn_icon /> appears at the top of your screen when VPN is active."</string>
+ <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> wants to set up a VPN connection that allows it to monitor network traffic. Only accept if you trust the source. <br /> <br /> <img src=vpn_icon /> appears on your screen when VPN is active."</string>
<string name="legacy_title" msgid="192936250066580964">"VPN is connected"</string>
<string name="session" msgid="6470628549473641030">"Session:"</string>
<string name="duration" msgid="3584782459928719435">"Duration:"</string>
diff --git a/packages/VpnDialogs/res/values-en-rXC/strings.xml b/packages/VpnDialogs/res/values-en-rXC/strings.xml
index 9d010e6..f5e2deb 100644
--- a/packages/VpnDialogs/res/values-en-rXC/strings.xml
+++ b/packages/VpnDialogs/res/values-en-rXC/strings.xml
@@ -18,6 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Connection request"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> wants to set up a VPN connection that allows it to monitor network traffic. Only accept if you trust the source. <br /> <br /> <img src=vpn_icon /> appears at the top of your screen when VPN is active."</string>
+ <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> wants to set up a VPN connection that allows it to monitor network traffic. Only accept if you trust the source. <br /> <br /> <img src=vpn_icon /> appears on your screen when VPN is active."</string>
<string name="legacy_title" msgid="192936250066580964">"VPN is connected"</string>
<string name="session" msgid="6470628549473641030">"Session:"</string>
<string name="duration" msgid="3584782459928719435">"Duration:"</string>
diff --git a/packages/VpnDialogs/res/values-es-rUS/strings.xml b/packages/VpnDialogs/res/values-es-rUS/strings.xml
index 21cfc04..108a24e 100644
--- a/packages/VpnDialogs/res/values-es-rUS/strings.xml
+++ b/packages/VpnDialogs/res/values-es-rUS/strings.xml
@@ -18,6 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Solicitud de conexión"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> quiere configurar una conexión VPN capaz de controlar el tráfico de la red. Acéptala solo si confías en la fuente. <br /> <br /> <img src=vpn_icon /> aparece en la parte superior de la pantalla cuando se activa la VPN."</string>
+ <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> quiere configurar una conexión VPN que le permita supervisar el tráfico de red. Solo acéptala si confías en la fuente. <br /> <br /> <img src=vpn_icon /> aparecerá en tu pantalla cuando se active la VPN."</string>
<string name="legacy_title" msgid="192936250066580964">"La VPN está conectada."</string>
<string name="session" msgid="6470628549473641030">"Sesión:"</string>
<string name="duration" msgid="3584782459928719435">"Duración:"</string>
diff --git a/packages/VpnDialogs/res/values-es/strings.xml b/packages/VpnDialogs/res/values-es/strings.xml
index 372147f..0eaf359 100644
--- a/packages/VpnDialogs/res/values-es/strings.xml
+++ b/packages/VpnDialogs/res/values-es/strings.xml
@@ -18,6 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Solicitud de conexión"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> quiere configurar una conexión VPN para controlar el tráfico de red. Solo debes aceptarla si confías en la fuente. <br /> <br /> <img src=vpn_icon /> aparece en la parte superior de la pantalla cuando se active la conexión VPN."</string>
+ <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> quiere configurar una conexión VPN que le permita monitorizar el tráfico de red. Acéptalo solo si confías en la fuente. <br /> <br /> <img src=vpn_icon /> aparecerá en la pantalla cuando la VPN esté activa."</string>
<string name="legacy_title" msgid="192936250066580964">"VPN conectada"</string>
<string name="session" msgid="6470628549473641030">"Sesión:"</string>
<string name="duration" msgid="3584782459928719435">"Duración:"</string>
diff --git a/packages/VpnDialogs/res/values-et/strings.xml b/packages/VpnDialogs/res/values-et/strings.xml
index c328cd7..3c7b3f3 100644
--- a/packages/VpnDialogs/res/values-et/strings.xml
+++ b/packages/VpnDialogs/res/values-et/strings.xml
@@ -18,6 +18,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Ühendamise taotlus"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> tahab seadistada VPN-i ühenduse, mis võimaldab jälgida võrguliiklust. Nõustuge ainult siis, kui usaldate seda allikat. <br /> <br /> <img src=vpn_icon /> kuvatakse ekraani ülaservas, kui VPN on aktiivne."</string>
+ <!-- no translation found for warning (5188957997628124947) -->
+ <skip />
<string name="legacy_title" msgid="192936250066580964">"VPN on ühendatud"</string>
<string name="session" msgid="6470628549473641030">"Seansid"</string>
<string name="duration" msgid="3584782459928719435">"Kestus:"</string>
diff --git a/packages/VpnDialogs/res/values-eu/strings.xml b/packages/VpnDialogs/res/values-eu/strings.xml
index a3b7716e..74c5378 100644
--- a/packages/VpnDialogs/res/values-eu/strings.xml
+++ b/packages/VpnDialogs/res/values-eu/strings.xml
@@ -18,6 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Konektatzeko eskaera"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> aplikazioak VPN bidezko konexioa ezarri nahi du sareko trafikoa kontrolatzeko. Iturburua fidagarria bada bakarrik baimendu. <br /> <br /> VPN konexioa aktibo dagoenean, <img src=vpn_icon /> agertuko da pantailaren goialdean."</string>
+ <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> aplikazioak VPN bidezko konexio bat konfiguratu nahi du sareko trafikoa gainbegiratzeko. Onartu soilik iturburuaz fidatzen bazara. <br /> <br /> <img src=vpn_icon /> agertzen da pantailan, VPNa aktibo dagoenean."</string>
<string name="legacy_title" msgid="192936250066580964">"VPN sarera konektatuta dago"</string>
<string name="session" msgid="6470628549473641030">"Saioa:"</string>
<string name="duration" msgid="3584782459928719435">"Iraupena:"</string>
diff --git a/packages/VpnDialogs/res/values-fa/strings.xml b/packages/VpnDialogs/res/values-fa/strings.xml
index 56f847c..77223cb8 100644
--- a/packages/VpnDialogs/res/values-fa/strings.xml
+++ b/packages/VpnDialogs/res/values-fa/strings.xml
@@ -18,6 +18,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"درخواست اتصال"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> میخواهد یک اتصال VPN راهاندازی کند که به آن امکان نظارت بر ترافیک شبکه را میدهد. فقط در صورتی بپذیرید که به منبع آن اطمینان دارید. هنگامی که VPN فعال شد، <br /> <br /> <img src=vpn_icon /> در بالای صفحه نمایش شما نشان داده میشود."</string>
+ <!-- no translation found for warning (5188957997628124947) -->
+ <skip />
<string name="legacy_title" msgid="192936250066580964">"VPN متصل است"</string>
<string name="session" msgid="6470628549473641030">"جلسه:"</string>
<string name="duration" msgid="3584782459928719435">"مدت زمان:"</string>
diff --git a/packages/VpnDialogs/res/values-fi/strings.xml b/packages/VpnDialogs/res/values-fi/strings.xml
index 91c918a..8abca06 100644
--- a/packages/VpnDialogs/res/values-fi/strings.xml
+++ b/packages/VpnDialogs/res/values-fi/strings.xml
@@ -18,6 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Yhteyspyyntö"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> haluaa tehdä asetukset VPN-yhteydellä, jonka kautta sovellus voi valvoa verkkoliikennettä. Hyväksy vain, jos lähde on luotettava. <br /> <br /> <img src=vpn_icon /> näkyy ruudun yläreunassa, kun VPN on käytössä."</string>
+ <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> haluaa muodostaa VPN-yhteyden, jonka avulla se voi valvoa verkkoliikennettä. Salli tämä vain, jos luotat lähteeseen. <br /> <br /> <img src=vpn_icon /> näkyy näytölläsi, kun VPN on aktiivinen."</string>
<string name="legacy_title" msgid="192936250066580964">"VPN on yhdistetty"</string>
<string name="session" msgid="6470628549473641030">"Käyttökerta"</string>
<string name="duration" msgid="3584782459928719435">"Kesto:"</string>
diff --git a/packages/VpnDialogs/res/values-fr-rCA/strings.xml b/packages/VpnDialogs/res/values-fr-rCA/strings.xml
index aa86c7c..876111c 100644
--- a/packages/VpnDialogs/res/values-fr-rCA/strings.xml
+++ b/packages/VpnDialogs/res/values-fr-rCA/strings.xml
@@ -18,6 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Demande de connexion"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> veut configurer une connexion RPV qui permet de surveiller le trafic réseau. N\'acceptez que si vous faites confiance à la source. <br /><br /><img src=vpn_icon/> s\'affiche dans le haut de votre écran lorsqu\'une connexion RPV est active."</string>
+ <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> veut configurer une connexion RPV qui permet de surveiller le trafic réseau. N\'acceptez que si vous faites confiance à la source. <br /> <br /> <img src=vpn_icon /> s\'affiche dans le haut de votre écran lorsqu\'une connexion RPV est active."</string>
<string name="legacy_title" msgid="192936250066580964">"RPV connecté"</string>
<string name="session" msgid="6470628549473641030">"Session :"</string>
<string name="duration" msgid="3584782459928719435">"Durée :"</string>
diff --git a/packages/VpnDialogs/res/values-fr/strings.xml b/packages/VpnDialogs/res/values-fr/strings.xml
index 7180119..7b6a950 100644
--- a/packages/VpnDialogs/res/values-fr/strings.xml
+++ b/packages/VpnDialogs/res/values-fr/strings.xml
@@ -18,6 +18,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Demande de connexion"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> souhaite configurer une connexion VPN qui lui permet de surveiller le trafic réseau. N\'acceptez que si vous faites confiance à la source. <br /> <br /> <img src=vpn_icon /> s\'affiche en haut de votre écran lorsqu\'une connexion VPN est active."</string>
+ <!-- no translation found for warning (5188957997628124947) -->
+ <skip />
<string name="legacy_title" msgid="192936250066580964">"VPN connecté"</string>
<string name="session" msgid="6470628549473641030">"Session :"</string>
<string name="duration" msgid="3584782459928719435">"Durée :"</string>
diff --git a/packages/VpnDialogs/res/values-gl/strings.xml b/packages/VpnDialogs/res/values-gl/strings.xml
index 8a66d08..cd8ee8d 100644
--- a/packages/VpnDialogs/res/values-gl/strings.xml
+++ b/packages/VpnDialogs/res/values-gl/strings.xml
@@ -18,6 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Solicitude de conexión"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> quere configurar unha conexión VPN que lle permite controlar o tráfico da rede. Acepta soamente se confías na fonte. <br /> <br /> <img src=vpn_icon /> aparece na parte superior da pantalla cando se activa a VPN."</string>
+ <string name="warning" product="tv" msgid="5188957997628124947">"A aplicación <xliff:g id="APP">%s</xliff:g> quere configurar unha conexión VPN que lle permita supervisar o tráfico de rede. Acepta só se confías nela. <br /> <br /> <img src=vpn_icon /> aparece na pantalla cando a VPN está activa."</string>
<string name="legacy_title" msgid="192936250066580964">"A VPN está conectada"</string>
<string name="session" msgid="6470628549473641030">"Sesión:"</string>
<string name="duration" msgid="3584782459928719435">"Duración:"</string>
diff --git a/packages/VpnDialogs/res/values-gu/strings.xml b/packages/VpnDialogs/res/values-gu/strings.xml
index 961711c..fd6e116 100644
--- a/packages/VpnDialogs/res/values-gu/strings.xml
+++ b/packages/VpnDialogs/res/values-gu/strings.xml
@@ -18,6 +18,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"કનેક્શન વિનંતી"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> VPN કનેક્શન સેટ કરવા માગે છે જે તેને નેટવર્ક ટ્રાફિક મૉનિટર કરવાની મંજૂરી આપે છે. જો તમને સ્રોત પર વિશ્વાસ હોય તો જ સ્વીકારો. <br /> <br /> <img src=vpn_icon /> તમારી સ્ક્રીનની ટોચ પર ત્યારે દેખાય છે જ્યારે VPN સક્રિય હોય છે."</string>
+ <!-- no translation found for warning (5188957997628124947) -->
+ <skip />
<string name="legacy_title" msgid="192936250066580964">"VPN કનેક્ટ કરેલું છે"</string>
<string name="session" msgid="6470628549473641030">"સત્ર:"</string>
<string name="duration" msgid="3584782459928719435">"અવધિ:"</string>
diff --git a/packages/VpnDialogs/res/values-hi/strings.xml b/packages/VpnDialogs/res/values-hi/strings.xml
index eed0858..916c25d 100644
--- a/packages/VpnDialogs/res/values-hi/strings.xml
+++ b/packages/VpnDialogs/res/values-hi/strings.xml
@@ -18,6 +18,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"कनेक्शन अनुरोध"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> वीपीएन कनेक्शन सेट अप करना चाहता है, जिससे वह नेटवर्क ट्रैफ़िक पर नज़र रख पाएगा. इसकी मंज़ूरी तभी दें जब आपको इस पर भरोसा हो. वीपीएन चालू होने पर <br /> <br /> <img src=vpn_icon /> आपकी स्क्रीन के सबसे ऊपर दिखाई देता है."</string>
+ <!-- no translation found for warning (5188957997628124947) -->
+ <skip />
<string name="legacy_title" msgid="192936250066580964">"VPN कनेक्ट है"</string>
<string name="session" msgid="6470628549473641030">"सत्र:"</string>
<string name="duration" msgid="3584782459928719435">"अवधि:"</string>
diff --git a/packages/VpnDialogs/res/values-hr/strings.xml b/packages/VpnDialogs/res/values-hr/strings.xml
index aa9e436..576d997 100644
--- a/packages/VpnDialogs/res/values-hr/strings.xml
+++ b/packages/VpnDialogs/res/values-hr/strings.xml
@@ -18,6 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Zahtjev za povezivanje"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> želi postaviti VPN vezu pomoću koje će moći nadzirati mrežni promet. Prihvatite samo ako smatrate izvor pouzdanim. Kada je VPN aktivan, pri vrhu zaslona prikazuje se <br /> <br /> <img src=vpn_icon />."</string>
+ <string name="warning" product="tv" msgid="5188957997628124947">"Aplikacija <xliff:g id="APP">%s</xliff:g> želi postaviti VPN vezu pomoću koje će moći nadzirati mrežni promet. Prihvatite samo ako smatrate izvor pouzdanim. Kad je VPN aktivan, na zaslonu se prikazuje ikona <br /> <br /> <img src=vpn_icon />."</string>
<string name="legacy_title" msgid="192936250066580964">"VPN je spojen"</string>
<string name="session" msgid="6470628549473641030">"Sesija"</string>
<string name="duration" msgid="3584782459928719435">"Trajanje:"</string>
diff --git a/packages/VpnDialogs/res/values-hu/strings.xml b/packages/VpnDialogs/res/values-hu/strings.xml
index 703aa79..4864484 100644
--- a/packages/VpnDialogs/res/values-hu/strings.xml
+++ b/packages/VpnDialogs/res/values-hu/strings.xml
@@ -18,6 +18,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Kapcsolódási kérés"</string>
<string name="warning" msgid="809658604548412033">"A(z) <xliff:g id="APP">%s</xliff:g> VPN kapcsolatot akar beállítani, amelynek segítségével figyelheti a hálózati forgalmat. Csak akkor fogadja el, ha megbízik a forrásban. <br /> <br /> Amikor a VPN aktív, <img src=vpn_icon /> ikon jelenik meg a képernyő tetején."</string>
+ <!-- no translation found for warning (5188957997628124947) -->
+ <skip />
<string name="legacy_title" msgid="192936250066580964">"A VPN csatlakoztatva van"</string>
<string name="session" msgid="6470628549473641030">"Munkamenet:"</string>
<string name="duration" msgid="3584782459928719435">"Időtartam:"</string>
diff --git a/packages/VpnDialogs/res/values-hy/strings.xml b/packages/VpnDialogs/res/values-hy/strings.xml
index c296c85..64053a4 100644
--- a/packages/VpnDialogs/res/values-hy/strings.xml
+++ b/packages/VpnDialogs/res/values-hy/strings.xml
@@ -17,7 +17,9 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Միացման հայց"</string>
- <string name="warning" msgid="809658604548412033">"«<xliff:g id="APP">%s</xliff:g>» հավելվածը ցանկանում է VPN կապ հաստատել՝ ցանցային երթևեկը հսկելու համար: Թույլատրեք, միայն եթե վստահում եք աղբյուրին: Երբ VPN-ն ակտիվ լինի, ձեր էկրանի վերին հատվածում կհայտնվի <br /> <br /> <img src=vpn_icon /> պատկերը:"</string>
+ <string name="warning" msgid="809658604548412033">"«<xliff:g id="APP">%s</xliff:g>» հավելվածը ցանկանում է VPN կապ հաստատել՝ ցանցային երթևեկը հսկելու համար: Թույլատրեք, միայն եթե վստահում եք աղբյուրին։ Երբ VPN-ն ակտիվ լինի, ձեր էկրանի վերին հատվածում կհայտնվի <br /> <br /> <img src=vpn_icon /> պատկերը:"</string>
+ <!-- no translation found for warning (5188957997628124947) -->
+ <skip />
<string name="legacy_title" msgid="192936250066580964">"VPN-ը կապակցված է"</string>
<string name="session" msgid="6470628549473641030">"Աշխատաշրջան`"</string>
<string name="duration" msgid="3584782459928719435">"Տևողությունը՝"</string>
@@ -25,7 +27,7 @@
<string name="data_received" msgid="4062776929376067820">"Ստացվել է՝"</string>
<string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> բայթ / <xliff:g id="NUMBER_1">%2$s</xliff:g> փաթեթ"</string>
<string name="always_on_disconnected_title" msgid="1906740176262776166">"Չի հաջողվում միանալ միշտ միացված VPN-ին"</string>
- <string name="always_on_disconnected_message" msgid="555634519845992917">"<xliff:g id="VPN_APP_0">%1$s</xliff:g>-ն այնպես է կարգավորված, որ միշտ միացած մնա, սակայն ներկայումս կապակցման խնդիր կա: Ձեր հեռախոսը կօգտագործի հանրային ցանցը, մինչև նորից կարողանա միանալ <xliff:g id="VPN_APP_1">%1$s</xliff:g>-ին:"</string>
+ <string name="always_on_disconnected_message" msgid="555634519845992917">"<xliff:g id="VPN_APP_0">%1$s</xliff:g>-ն այնպես է կարգավորված, որ միշտ միացած մնա, սակայն ներկայումս կապակցման խնդիր կա: Ձեր հեռախոսը կօգտագործի հանրային ցանցը, մինչև նորից կարողանա միանալ <xliff:g id="VPN_APP_1">%1$s</xliff:g>-ին։"</string>
<string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"<xliff:g id="VPN_APP">%1$s</xliff:g>-ն այնպես է կարգավորված, որ միշտ միացած մնա, սակայն ներկայումս կապակցման խնդիր կա: Մինչև VPN-ը նորից չմիանա, դուք կապ չեք ունենա:"</string>
<string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string>
<string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"Փոխել VPN-ի կարգավորումները"</string>
diff --git a/packages/VpnDialogs/res/values-in/strings.xml b/packages/VpnDialogs/res/values-in/strings.xml
index 18ef372a..059008f 100644
--- a/packages/VpnDialogs/res/values-in/strings.xml
+++ b/packages/VpnDialogs/res/values-in/strings.xml
@@ -18,6 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Permintaan sambungan"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> ingin menyiapkan sambungan VPN yang memungkinkannya memantau traffic jaringan. Terima hanya jika Anda memercayai sumber. <br /> <br /> <img src=vpn_icon /> muncul di bagian atas layar Anda saat VPN aktif."</string>
+ <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> ingin menyiapkan koneksi VPN yang memungkinkannya memantau traffic jaringan. Hanya terima jika Anda memercayai sumbernya. <br /> <br /> <img src=vpn_icon /> muncul di layar bila VPN aktif."</string>
<string name="legacy_title" msgid="192936250066580964">"VPN tersambung"</string>
<string name="session" msgid="6470628549473641030">"Sesi:"</string>
<string name="duration" msgid="3584782459928719435">"Durasi:"</string>
diff --git a/packages/VpnDialogs/res/values-is/strings.xml b/packages/VpnDialogs/res/values-is/strings.xml
index 70fb40f..53a5c02 100644
--- a/packages/VpnDialogs/res/values-is/strings.xml
+++ b/packages/VpnDialogs/res/values-is/strings.xml
@@ -18,6 +18,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Beiðni um tengingu"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> vill setja upp VPN-tengingu til þess að geta fylgst með netumferð. Samþykktu þetta aðeins ef þú treystir upprunanum. <br /> <br /> <img src=vpn_icon /> birtist efst á skjánum þegar VPN er virkt."</string>
+ <!-- no translation found for warning (5188957997628124947) -->
+ <skip />
<string name="legacy_title" msgid="192936250066580964">"VPN er tengt"</string>
<string name="session" msgid="6470628549473641030">"Lota:"</string>
<string name="duration" msgid="3584782459928719435">"Tímalengd:"</string>
diff --git a/packages/VpnDialogs/res/values-it/strings.xml b/packages/VpnDialogs/res/values-it/strings.xml
index 2602493..c443c51 100644
--- a/packages/VpnDialogs/res/values-it/strings.xml
+++ b/packages/VpnDialogs/res/values-it/strings.xml
@@ -18,6 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Richiesta di connessione"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> vuole impostare una connessione VPN che le consenta di monitorare il traffico di rete. Accetta soltanto se ritieni la fonte attendibile. Quando la connessione VPN è attiva, nella parte superiore dello schermo viene visualizzata l\'icona <br /> <br /> <img src=vpn_icon />."</string>
+ <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> vuole configurare una connessione VPN che le consenta di monitorare il traffico di rete. Accetta soltanto se ritieni la fonte attendibile. Quando la connessione VPN è attiva, sullo schermo viene visualizzata l\'icona <br /> <br /> <img src=vpn_icon />."</string>
<string name="legacy_title" msgid="192936250066580964">"VPN connessa"</string>
<string name="session" msgid="6470628549473641030">"Sessione:"</string>
<string name="duration" msgid="3584782459928719435">"Durata:"</string>
diff --git a/packages/VpnDialogs/res/values-iw/strings.xml b/packages/VpnDialogs/res/values-iw/strings.xml
index ebabd4e..4156944 100644
--- a/packages/VpnDialogs/res/values-iw/strings.xml
+++ b/packages/VpnDialogs/res/values-iw/strings.xml
@@ -18,6 +18,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"בקשת חיבור"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> רוצה להגדיר חיבור VPN שיאפשר לו לפקח על תעבורת הרשת. אשר את הבקשה רק אם אתה נותן אמון במקור. <br /> <br /> <img src=vpn_icon /> מופיע בחלק העליון של המסך כאשר VPN פעיל."</string>
+ <!-- no translation found for warning (5188957997628124947) -->
+ <skip />
<string name="legacy_title" msgid="192936250066580964">"VPN מחובר"</string>
<string name="session" msgid="6470628549473641030">"הפעלה"</string>
<string name="duration" msgid="3584782459928719435">"משך:"</string>
diff --git a/packages/VpnDialogs/res/values-ja/strings.xml b/packages/VpnDialogs/res/values-ja/strings.xml
index 8480692..e03e9d3 100644
--- a/packages/VpnDialogs/res/values-ja/strings.xml
+++ b/packages/VpnDialogs/res/values-ja/strings.xml
@@ -18,6 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"接続リクエスト"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> がネットワーク トラフィックを監視するため VPN 接続をセットアップしようとしています。信頼できるソースである場合にのみ許可してください。<br /> <br /> VPN がアクティブになると画面の上部に <img src=vpn_icon /> が表示されます。"</string>
+ <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> は、ネットワーク トラフィックを監視できるよう、VPN 接続を設定するよう求めています。ソースを信頼できる場合のみ、許可してください。VPN が有効になると、画面に <br /> <br /> <img src=vpn_icon /> が表示されます。"</string>
<string name="legacy_title" msgid="192936250066580964">"VPN接続済み"</string>
<string name="session" msgid="6470628549473641030">"セッション:"</string>
<string name="duration" msgid="3584782459928719435">"期間:"</string>
diff --git a/packages/VpnDialogs/res/values-ka/strings.xml b/packages/VpnDialogs/res/values-ka/strings.xml
index e5a0753..9c4388e 100644
--- a/packages/VpnDialogs/res/values-ka/strings.xml
+++ b/packages/VpnDialogs/res/values-ka/strings.xml
@@ -18,6 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"კავშირის მოთხოვნა"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> სურს დააყენოს VPN კავშირი, რაც ქსელის ტრაფიკის მონიტორინგის საშუალებას იძლევა. მიიღოთ მხოლოდ ისეთ შემთხვევაში, თუ წყაროს ენდობით. <br /> <br /> <img src=vpn_icon /> თქვენი ეკრანის სიის თავში გამოჩნდება, როდესაც VPN აქტიურია."</string>
+ <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g>-ს სურს დააყენოს VPN კავშირი, რაც ქსელის ტრაფიკის მონიტორინგის საშუალებას იძლევა. დათანხმდით მხოლოდ იმ შემთხვევაში, თუ წყაროს ენდობით. <br /> <br /> <img src=vpn_icon /> თქვენს ეკრანზე გამოჩნდება, როდესაც VPN აქტიურია."</string>
<string name="legacy_title" msgid="192936250066580964">"VPN დაკავშირებულია"</string>
<string name="session" msgid="6470628549473641030">"სესია:"</string>
<string name="duration" msgid="3584782459928719435">"ხანგრძლივობა:"</string>
diff --git a/packages/VpnDialogs/res/values-kk/strings.xml b/packages/VpnDialogs/res/values-kk/strings.xml
index 79f79c3..4948217 100644
--- a/packages/VpnDialogs/res/values-kk/strings.xml
+++ b/packages/VpnDialogs/res/values-kk/strings.xml
@@ -18,6 +18,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Байланысты сұрау"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> VPN байланысын орнатқысы келеді, бұл оған желілік трафикті бақылауға мүмкіндік береді. Көзге сенсеңіз ғана қабылдаңыз. VPN белсенді болғанда экранның жоғарғы жағында <br /> <br /> <img src=vpn_icon /> көрсетіледі."</string>
+ <!-- no translation found for warning (5188957997628124947) -->
+ <skip />
<string name="legacy_title" msgid="192936250066580964">"ВЖЖ қосылған"</string>
<string name="session" msgid="6470628549473641030">"Сессия:"</string>
<string name="duration" msgid="3584782459928719435">"Ұзақтығы:"</string>
diff --git a/packages/VpnDialogs/res/values-km/strings.xml b/packages/VpnDialogs/res/values-km/strings.xml
index 06f34db..0ed2e84b 100644
--- a/packages/VpnDialogs/res/values-km/strings.xml
+++ b/packages/VpnDialogs/res/values-km/strings.xml
@@ -18,6 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"សំណើសុំការតភ្ជាប់"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> ចង់បង្កើតការតភ្ជាប់ VPN ដែលអនុញ្ញាតឲ្យវាត្រួតពិនិត្យចរាចរបណ្ដាញ។ ព្រមទទួល ប្រសិនបើអ្នកទុកចិត្តលើប្រភពតែប៉ុណ្ណោះ។ <br /> <br /> <img src=vpn_icon /> នឹងលេចឡើងនៅផ្នែកខាងលើនៃអេក្រង់របស់អ្នក ពេល VPN សកម្ម។"</string>
+ <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> ចង់រៀបចំការតភ្ជាប់ VPN ដែលអនុញ្ញាតឱ្យវាត្រួតពិនិត្យចរាចរណ៍បណ្តាញ។ យល់ព្រម ប្រសិនបើអ្នកជឿទុកចិត្តលើប្រភពនេះតែប៉ុណ្ណោះ។ <br /> <br /> <img src=vpn_icon /> បង្ហាញនៅលើអេក្រង់របស់អ្នក នៅពេល VPN កំពុងដំណើរការ។"</string>
<string name="legacy_title" msgid="192936250066580964">"បានភ្ជាប់ VPN"</string>
<string name="session" msgid="6470628549473641030">"សម័យ៖"</string>
<string name="duration" msgid="3584782459928719435">"ថិរវេលា៖"</string>
diff --git a/packages/VpnDialogs/res/values-kn/strings.xml b/packages/VpnDialogs/res/values-kn/strings.xml
index 040cd6c..3ebabe3 100644
--- a/packages/VpnDialogs/res/values-kn/strings.xml
+++ b/packages/VpnDialogs/res/values-kn/strings.xml
@@ -18,6 +18,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"ಸಂಪರ್ಕ ವಿನಂತಿ"</string>
<string name="warning" msgid="809658604548412033">"ನೆಟ್ವರ್ಕ್ ಟ್ರಾಫಿಕ್ ಅನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಲು ಅನುಮತಿಸುವಂತಹ VPN ಸಂಪರ್ಕವನ್ನು ಹೊಂದಿಸಲು <xliff:g id="APP">%s</xliff:g> ಬಯಸುತ್ತದೆ. ನೀವು ಮೂಲವನ್ನು ನಂಬಿದರೆ ಮಾತ್ರ ಸಮ್ಮತಿಸಿ. VPN ಸಕ್ರಿಯವಾಗಿರುವಾಗ ನಿಮ್ಮ ಪರದೆಯ ಮೇಲ್ಭಾಗದಲ್ಲಿ <br /> <br /> <img src=vpn_icon /> ಗೋರಿಸುತ್ತದೆ."</string>
+ <!-- no translation found for warning (5188957997628124947) -->
+ <skip />
<string name="legacy_title" msgid="192936250066580964">"VPN ಸಂಪರ್ಕಗೊಂಡಿದೆ"</string>
<string name="session" msgid="6470628549473641030">"ಸೆಷನ್:"</string>
<string name="duration" msgid="3584782459928719435">"ಅವಧಿ:"</string>
diff --git a/packages/VpnDialogs/res/values-ko/strings.xml b/packages/VpnDialogs/res/values-ko/strings.xml
index 6ad4976..6e179bb 100644
--- a/packages/VpnDialogs/res/values-ko/strings.xml
+++ b/packages/VpnDialogs/res/values-ko/strings.xml
@@ -18,6 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"연결 요청"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g>에서 네트워크 트래픽을 모니터링하도록 허용하는 VPN 연결을 설정하려고 합니다. 출처를 신뢰할 수 있는 경우에만 수락하세요. VPN이 활성화되면 <br /> <br /> <img src=vpn_icon />이 화면 위에 표시됩니다."</string>
+ <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g>에서 네트워크 트래픽을 모니터링할 수 있도록 VPN 연결을 설정하려고 합니다. 소스를 신뢰할 수 있는 경우에만 수락하세요. VPN이 활성 상태일 때는 <br /> <br /> <img src=vpn_icon /> 아이콘이 화면에 표시됩니다."</string>
<string name="legacy_title" msgid="192936250066580964">"VPN이 연결되었습니다."</string>
<string name="session" msgid="6470628549473641030">"세션:"</string>
<string name="duration" msgid="3584782459928719435">"기간:"</string>
diff --git a/packages/VpnDialogs/res/values-ky/strings.xml b/packages/VpnDialogs/res/values-ky/strings.xml
index 23c9be8..4083665 100644
--- a/packages/VpnDialogs/res/values-ky/strings.xml
+++ b/packages/VpnDialogs/res/values-ky/strings.xml
@@ -18,6 +18,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Туташуу сурамы"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> тармактык трафикти көзөмөлдөөгө уруксат берген VPN туташуусун орноткусу келет. Аны булакка ишенсеңиз гана кабыл алыңыз. <br /> <br /> <img src=vpn_icon /> VPN иштеп турганда экраныңыздын жогору жагынан көрүнөт."</string>
+ <!-- no translation found for warning (5188957997628124947) -->
+ <skip />
<string name="legacy_title" msgid="192936250066580964">"VPN байланышта"</string>
<string name="session" msgid="6470628549473641030">"Сессия:"</string>
<string name="duration" msgid="3584782459928719435">"Узактыгы:"</string>
diff --git a/packages/VpnDialogs/res/values-lo/strings.xml b/packages/VpnDialogs/res/values-lo/strings.xml
index c591308..cec69f0 100644
--- a/packages/VpnDialogs/res/values-lo/strings.xml
+++ b/packages/VpnDialogs/res/values-lo/strings.xml
@@ -18,6 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"ການຮ້ອງຂໍການເຊື່ອມຕໍ່"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> ຕ້ອງການຕັ້ງຄ່າການເຊື່ອມຕໍ່ VPN ທີ່ອະນຸຍາດໃຫ້ຕິດຕາມທຣາບຟິກເຄືອຂ່າຍໄດ້. ທ່ານຄວນຍິນຍອມສະເພາະໃນກໍລະນີທີ່ທ່ານເຊື່ອຖືແຫລ່ງຂໍ້ມູນເທົ່ານັ້ນ. <br /> <br /> <img src=vpn_icon /> ຈະປາກົດຢູ່ດ້ານເທິງຂອງໜ້າຈໍເມື່ອມີການເປີດໃຊ້ VPN."</string>
+ <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> ຕ້ອງການຕັ້ງຄ່າການເຊື່ອມຕໍ່ VPN ທີ່ອະນຸຍາດໃຫ້ມັນກວດກາການຈາລະຈອນເຄືອຂ່າຍໄດ້. ໃຫ້ຍອມຮັບສະເພາະໃນກໍລະນີທີ່ທ່ານເຊື່ອຖືແຫຼ່ງທີ່ມາເທົ່ານັ້ນ. <br /> <br /> <img src=vpn_icon /> ຈະປາກົດຢູ່ໜ້າຈໍຂອງທ່ານເມື່ອເປີດໃຊ້ VPN."</string>
<string name="legacy_title" msgid="192936250066580964">"ເຊື່ອມຕໍ່ VPN ແລ້ວ"</string>
<string name="session" msgid="6470628549473641030">"ເຊສຊັນ:"</string>
<string name="duration" msgid="3584782459928719435">"ໄລຍະເວລາ:"</string>
diff --git a/packages/VpnDialogs/res/values-lt/strings.xml b/packages/VpnDialogs/res/values-lt/strings.xml
index 8846310..1f86180d 100644
--- a/packages/VpnDialogs/res/values-lt/strings.xml
+++ b/packages/VpnDialogs/res/values-lt/strings.xml
@@ -18,6 +18,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Ryšio užklausa"</string>
<string name="warning" msgid="809658604548412033">"„<xliff:g id="APP">%s</xliff:g>“ nori nustatyti VPN ryšį, kad galėtų stebėti tinklo srautą. Sutikite, tik jei pasitikite šaltiniu. <br /> <br /> <img src=vpn_icon /> rodoma ekrano viršuje, kai VPN aktyvus."</string>
+ <!-- no translation found for warning (5188957997628124947) -->
+ <skip />
<string name="legacy_title" msgid="192936250066580964">"VPN prijungtas"</string>
<string name="session" msgid="6470628549473641030">"Sesija"</string>
<string name="duration" msgid="3584782459928719435">"Trukmė:"</string>
diff --git a/packages/VpnDialogs/res/values-lv/strings.xml b/packages/VpnDialogs/res/values-lv/strings.xml
index 07625b6..71da870 100644
--- a/packages/VpnDialogs/res/values-lv/strings.xml
+++ b/packages/VpnDialogs/res/values-lv/strings.xml
@@ -18,6 +18,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Savienojuma pieprasījums"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> vēlas izveidot VPN savienojumu, kas ļaus pārraudzīt tīkla datplūsmu. Piekrītiet tikai tad, ja uzticaties avotam. <br /> <br /> <img src=vpn_icon /> tiek rādīta ekrāna augšdaļā, kad darbojas VPN."</string>
+ <!-- no translation found for warning (5188957997628124947) -->
+ <skip />
<string name="legacy_title" msgid="192936250066580964">"Ir izveidots savienojums ar VPN"</string>
<string name="session" msgid="6470628549473641030">"Sesija:"</string>
<string name="duration" msgid="3584782459928719435">"Ilgums:"</string>
diff --git a/packages/VpnDialogs/res/values-mk/strings.xml b/packages/VpnDialogs/res/values-mk/strings.xml
index b5a64f2..689d028 100644
--- a/packages/VpnDialogs/res/values-mk/strings.xml
+++ b/packages/VpnDialogs/res/values-mk/strings.xml
@@ -18,6 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Барање за поврзување"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> сака да постави поврзување со ВПН коешто му дозволува да го набљудува сообраќајот на мрежата. Прифатете само доколку му верувате на изворот. <br /> <br /> <img src=vpn_icon /> се појавува на врвот на екранот кога ВПН е активна."</string>
+ <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> сака да постави поврзување со VPN што ќе дозволи да го набљудува сообраќајот на мрежата. Прифатете само ако му верувате на изворот. <br /> <br /> <img src=vpn_icon /> ќе се појави на екранот кога ќе се активира VPN."</string>
<string name="legacy_title" msgid="192936250066580964">"VPN е поврзана"</string>
<string name="session" msgid="6470628549473641030">"Сесија:"</string>
<string name="duration" msgid="3584782459928719435">"Времетраење:"</string>
@@ -30,7 +31,7 @@
<string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string>
<string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"Променете ги поставките за VPN"</string>
<string name="configure" msgid="4905518375574791375">"Конфигурирај"</string>
- <string name="disconnect" msgid="971412338304200056">"Исклучи"</string>
+ <string name="disconnect" msgid="971412338304200056">"Прекини врска"</string>
<string name="open_app" msgid="3717639178595958667">"Отвори ја апликацијата"</string>
<string name="dismiss" msgid="6192859333764711227">"Отфрли"</string>
</resources>
diff --git a/packages/VpnDialogs/res/values-ml/strings.xml b/packages/VpnDialogs/res/values-ml/strings.xml
index 680d0ef..a298caa 100644
--- a/packages/VpnDialogs/res/values-ml/strings.xml
+++ b/packages/VpnDialogs/res/values-ml/strings.xml
@@ -18,6 +18,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"കണക്ഷൻ അഭ്യർത്ഥന"</string>
<string name="warning" msgid="809658604548412033">"നെറ്റ്വർക്ക് ട്രാഫിക്ക് നിരീക്ഷിക്കാൻ അനുവദിക്കുന്ന ഒരു VPN കണക്ഷൻ <xliff:g id="APP">%s</xliff:g> സജ്ജീകരിക്കേണ്ടതുണ്ട്. ഉറവിടം പരിചിതമാണെങ്കിൽ മാത്രം അംഗീകരിക്കുക. VPN സജീവമാകുമ്പോൾ <br /> <br /> <img src=vpn_icon /> നിങ്ങളുടെ സ്ക്രീനിന്റെ മുകളിൽ ദൃശ്യമാകുന്നു."</string>
+ <!-- no translation found for warning (5188957997628124947) -->
+ <skip />
<string name="legacy_title" msgid="192936250066580964">"VPN കണക്റ്റുചെയ്തു"</string>
<string name="session" msgid="6470628549473641030">"സെഷൻ:"</string>
<string name="duration" msgid="3584782459928719435">"സമയദൈര്ഘ്യം:"</string>
diff --git a/packages/VpnDialogs/res/values-mn/strings.xml b/packages/VpnDialogs/res/values-mn/strings.xml
index 9aa104a..1dd4c15 100644
--- a/packages/VpnDialogs/res/values-mn/strings.xml
+++ b/packages/VpnDialogs/res/values-mn/strings.xml
@@ -18,6 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Холболтын хүсэлт"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> нь сүлжээний трафикыг хянах боломж бүхий VPN холболт үүсгэхийг хүсэж байна. Та зөвхөн эх үүсвэрт итгэж байгаа бол зөвшөөрнө үү. <br /> <br /> <img src=vpn_icon /> таны дэлгэц дээр VPN идэвхтэй үед гарч ирнэ."</string>
+ <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> нь түүнд сүлжээний ачааллыг хянах боломжийг олгодог VPN холболт тохируулахыг хүсэж байна. Зөвхөн та эх сурвалжид итгэдэг тохиолдолд зөвшөөрнө үү. VPN идэвхтэй үед таны дэлгэц дээр <br /> <br /> <img src=vpn_icon /> харагдана."</string>
<string name="legacy_title" msgid="192936250066580964">"VPN холбогдов"</string>
<string name="session" msgid="6470628549473641030">"Сешн:"</string>
<string name="duration" msgid="3584782459928719435">"Үргэлжлэх хугацаа:"</string>
diff --git a/packages/VpnDialogs/res/values-mr/strings.xml b/packages/VpnDialogs/res/values-mr/strings.xml
index 41d7429..6caccf7 100644
--- a/packages/VpnDialogs/res/values-mr/strings.xml
+++ b/packages/VpnDialogs/res/values-mr/strings.xml
@@ -18,18 +18,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"कनेक्शन विनंती"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> नेटवर्क रहदारीचे परीक्षण करण्यासाठी त्यास अनुमती देणारे VPN कनेक्शन सेट करू इच्छितो. तुम्हाला स्रोत विश्वसनीय वाटत असेल तरच स्वीकार करा. <br /> <br /> <img src=vpn_icon /> VPN सक्रिय असताना आपल्या स्क्रीनच्या शीर्षावर दिसते."</string>
+ <!-- no translation found for warning (5188957997628124947) -->
+ <skip />
<string name="legacy_title" msgid="192936250066580964">"VPN कनेक्ट केले"</string>
<string name="session" msgid="6470628549473641030">"सत्र:"</string>
<string name="duration" msgid="3584782459928719435">"कालावधी:"</string>
<string name="data_transmitted" msgid="7988167672982199061">"प्रेषित:"</string>
<string name="data_received" msgid="4062776929376067820">"प्राप्त झाले:"</string>
<string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> बाइट / <xliff:g id="NUMBER_1">%2$s</xliff:g> पॅकेट"</string>
- <string name="always_on_disconnected_title" msgid="1906740176262776166">"कायम चालू असलेल्या VPN शी कनेक्ट करू शकत नाही"</string>
+ <string name="always_on_disconnected_title" msgid="1906740176262776166">"कायम सुरू असलेल्या VPN शी कनेक्ट करू शकत नाही"</string>
<string name="always_on_disconnected_message" msgid="555634519845992917">"<xliff:g id="VPN_APP_0">%1$s</xliff:g> हे पूर्ण वेळ कनेक्ट राहण्यासाठी सेट अप केलेले आहे, पण हे आता कनेक्ट होऊ शकत नाही. <xliff:g id="VPN_APP_1">%1$s</xliff:g> शी पुन्हा कनेक्ट होईपर्यंत तुमचा फोन सार्वजनिक नेटवर्क वापरेल."</string>
<string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"<xliff:g id="VPN_APP">%1$s</xliff:g> हे पूर्ण वेळ कनेक्ट राहण्यासाठी सेट अप केलेले आहे, पण हे आता कनेक्ट होऊ शकत नाही. VPN पुन्हा कनेक्ट होईपर्यंत तुमच्याकडे कनेक्शन नसेल."</string>
<string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string>
<string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"VPN सेटिंग्ज बदला"</string>
- <string name="configure" msgid="4905518375574791375">"कॉन्फिगर करा"</string>
+ <string name="configure" msgid="4905518375574791375">"कॉंफिगर करा"</string>
<string name="disconnect" msgid="971412338304200056">"डिस्कनेक्ट करा"</string>
<string name="open_app" msgid="3717639178595958667">"अॅप उघडा"</string>
<string name="dismiss" msgid="6192859333764711227">"डिसमिस करा"</string>
diff --git a/packages/VpnDialogs/res/values-ms/strings.xml b/packages/VpnDialogs/res/values-ms/strings.xml
index b489f2e..c9961d2 100644
--- a/packages/VpnDialogs/res/values-ms/strings.xml
+++ b/packages/VpnDialogs/res/values-ms/strings.xml
@@ -18,6 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Permintaan sambungan"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> ingin menyediakan sambungan VPN yang membenarkan apl memantau trafik rangkaian. Terima hanya jika anda mempercayai sumber. <br /> <br /> <img src=vpn_icon /> terpapar pada bahagian atas skrin anda apabila VPN aktif."</string>
+ <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> ingin menyediakan sambungan VPN yang membenarkan apl tersebut memantau trafik rangkaian. Hanya terima jika anda mempercayai sumber tersebut. <br /> <br /> <img src=vpn_icon /> muncul pada skrin anda apabila VPN aktif."</string>
<string name="legacy_title" msgid="192936250066580964">"VPN telah disambungkan"</string>
<string name="session" msgid="6470628549473641030">"Sesi:"</string>
<string name="duration" msgid="3584782459928719435">"Tempoh:"</string>
diff --git a/packages/VpnDialogs/res/values-my/strings.xml b/packages/VpnDialogs/res/values-my/strings.xml
index 9d60ff4..bda925f 100644
--- a/packages/VpnDialogs/res/values-my/strings.xml
+++ b/packages/VpnDialogs/res/values-my/strings.xml
@@ -18,6 +18,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"ချိတ်ဆက်ရန် တောင်းဆိုချက်"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> က ကွန်ရက် လုပ်ငန်းကို စောင့်ကြည့်ခွင့် ပြုမည့် VPN ချိတ်ဆက်မှုကို ထူထောင်လိုသည်။ ရင်းမြစ်ကို သင်က ယုံကြည်မှသာ လက်ခံပါ။ <br /> <br /> <img src=vpn_icon /> မှာ VPN အလုပ်လုပ်နေလျှင် သင်၏ မျက်နှာပြင် ထိပ်မှာ ပေါ်လာမည်။"</string>
+ <!-- no translation found for warning (5188957997628124947) -->
+ <skip />
<string name="legacy_title" msgid="192936250066580964">"VPNနှင့်ချိတ်ဆက်ထားသည်"</string>
<string name="session" msgid="6470628549473641030">"သတ်မှတ်ပေးထားသည့်အချိန်:"</string>
<string name="duration" msgid="3584782459928719435">"အချိန်ကာလ-"</string>
@@ -30,7 +32,7 @@
<string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string>
<string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"VPN ဆက်တင်များ ပြောင်းရန်"</string>
<string name="configure" msgid="4905518375574791375">"ပုံပေါ်စေသည်"</string>
- <string name="disconnect" msgid="971412338304200056">"ချိတ်ဆက်ခြင်းရပ်ရန်"</string>
+ <string name="disconnect" msgid="971412338304200056">"ချိတ်ဆက်မှုဖြုတ်ရန်"</string>
<string name="open_app" msgid="3717639178595958667">"အက်ပ်ကို ဖွင့်ရန်"</string>
<string name="dismiss" msgid="6192859333764711227">"ပယ်ရန်"</string>
</resources>
diff --git a/packages/VpnDialogs/res/values-nb/strings.xml b/packages/VpnDialogs/res/values-nb/strings.xml
index be572d4..eaa2c17 100644
--- a/packages/VpnDialogs/res/values-nb/strings.xml
+++ b/packages/VpnDialogs/res/values-nb/strings.xml
@@ -18,6 +18,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Tilkoblingsforespørsel"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> ønsker å bruke en VPN-tilkobling som tillater at appen overvåker nettverkstrafikken. Du bør bare godta dette hvis du stoler på kilden. <br /> <br /> <img src=vpn_icon /> vises øverst på skjermen din når VPN er aktivert."</string>
+ <!-- no translation found for warning (5188957997628124947) -->
+ <skip />
<string name="legacy_title" msgid="192936250066580964">"VPN er tilkoblet"</string>
<string name="session" msgid="6470628549473641030">"Økt:"</string>
<string name="duration" msgid="3584782459928719435">"Varighet:"</string>
diff --git a/packages/VpnDialogs/res/values-ne/strings.xml b/packages/VpnDialogs/res/values-ne/strings.xml
index b716c35..a248d6d8 100644
--- a/packages/VpnDialogs/res/values-ne/strings.xml
+++ b/packages/VpnDialogs/res/values-ne/strings.xml
@@ -18,6 +18,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"जडान अनुरोध"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> ले नेटवर्क यातायात अनुगमन गर्न अनुमति दिने VPN जडान स्थापना गर्न चाहन्छ। तपाईँले स्रोत भरोसा छ भने मात्र स्वीकार गर्नुहोस्। <br /> <br /> <img src=vpn_icon /> जब VPN सक्रिय हुन्छ आफ्नो स्क्रिनको माथि देखा पर्छन्।"</string>
+ <!-- no translation found for warning (5188957997628124947) -->
+ <skip />
<string name="legacy_title" msgid="192936250066580964">"VPN जोडिएको छ"</string>
<string name="session" msgid="6470628549473641030">"सत्र:"</string>
<string name="duration" msgid="3584782459928719435">"अवधि:"</string>
@@ -30,7 +32,7 @@
<string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string>
<string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"VPN सम्बन्धी सेटिङहरू परिवर्तन गर्नुहोस्"</string>
<string name="configure" msgid="4905518375574791375">"कन्फिगर गर्नुहोस्"</string>
- <string name="disconnect" msgid="971412338304200056">"विच्छेदन गर्नुहोस्"</string>
- <string name="open_app" msgid="3717639178595958667">"अनुप्रयोग खोल्नुहोस्"</string>
+ <string name="disconnect" msgid="971412338304200056">"डिस्कनेक्ट गर्नुहोस्"</string>
+ <string name="open_app" msgid="3717639178595958667">"एप खोल्नुहोस्"</string>
<string name="dismiss" msgid="6192859333764711227">"खारेज गर्नुहोस्"</string>
</resources>
diff --git a/packages/VpnDialogs/res/values-nl/strings.xml b/packages/VpnDialogs/res/values-nl/strings.xml
index 8073b09..33f8a89 100644
--- a/packages/VpnDialogs/res/values-nl/strings.xml
+++ b/packages/VpnDialogs/res/values-nl/strings.xml
@@ -18,6 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Verbindingsverzoek"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> wil een VPN-verbinding opzetten om netwerkverkeer te controleren. Accepteer het verzoek alleen als je de bron vertrouwt. <br /> <br /> <img src=vpn_icon /> wordt boven aan je scherm weergegeven wanneer VPN actief is."</string>
+ <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> wil een VPN-verbinding instellen waarmee de app het netwerkverkeer kan bijhouden. Accepteer dit alleen als je de bron vertrouwt. <br /> <br /> <img src=vpn_icon /> verschijnt op je scherm als het VPN actief is."</string>
<string name="legacy_title" msgid="192936250066580964">"Verbinding met VPN"</string>
<string name="session" msgid="6470628549473641030">"Sessie:"</string>
<string name="duration" msgid="3584782459928719435">"Duur:"</string>
diff --git a/packages/VpnDialogs/res/values-or/strings.xml b/packages/VpnDialogs/res/values-or/strings.xml
index f1122eb..f37814e 100644
--- a/packages/VpnDialogs/res/values-or/strings.xml
+++ b/packages/VpnDialogs/res/values-or/strings.xml
@@ -18,6 +18,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"ସଂଯୋଗ ଅନୁରୋଧ"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> ଏକ VPN ସଂଯୋଗ ସେଟ୍ ଅପ୍ କରିବାକୁ ଚାହେଁ, ଯାହା ଏହି ନେଟ୍ୱର୍କର ଟ୍ରାଫିକକୁ ମନିଟର୍ କରିବାକୁ ଅନୁମତି ଦିଏ। ଆପଣ ସୋର୍ସ ଉପରେ ବିଶ୍ୱାସ କରିବା ବଦଳରେ କେବଳ ସ୍ୱୀକାର କରନ୍ତୁ। <br /> <br /> <img src=vpn_icon /> VPN ସକ୍ରିୟ ଥିବାବେଳେ ଏହା ଆପଣଙ୍କ ସ୍କ୍ରୀନ୍ର ଉପରେ ଦେଖାଯାଏ।"</string>
+ <!-- no translation found for warning (5188957997628124947) -->
+ <skip />
<string name="legacy_title" msgid="192936250066580964">"VPN ସଂଯୋଗ ହେଲା"</string>
<string name="session" msgid="6470628549473641030">"ସେସନ୍:"</string>
<string name="duration" msgid="3584782459928719435">"ଅବଧି:"</string>
@@ -28,7 +30,7 @@
<string name="always_on_disconnected_message" msgid="555634519845992917">"<xliff:g id="VPN_APP_0">%1$s</xliff:g> ସବୁ ସମୟରେ କନେକ୍ଟ ହୋଇ ରହିବା ପାଇଁ ସେଟଅପ୍ କରାଯାଇଛି। ଆପଣଙ୍କ ଫୋନ୍, <xliff:g id="VPN_APP_1">%1$s</xliff:g> ସହ କନେକ୍ଟ ନହେବା ପର୍ଯ୍ୟନ୍ତ ଏକ ପବ୍ଲିକ୍ ନେଟ୍ୱର୍କ ବ୍ୟବହାର କରିବ।"</string>
<string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"<xliff:g id="VPN_APP">%1$s</xliff:g> ସବୁ ସମୟରେ କନେକ୍ଟ ହୋଇରହିବାକୁ ସେଟଅପ୍ କରାଯାଇଛି, କିନ୍ତୁ ଏହା ବର୍ତ୍ତମାନ କନେକ୍ଟ କରିପାରୁ ନାହିଁ। VPN ପୁଣି କନେକ୍ଟ ନହେବା ପର୍ଯ୍ୟନ୍ତ ଆପଣଙ୍କର କୌଣସି କନେକ୍ସନ୍ ରହିବନାହିଁ।"</string>
<string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string>
- <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"VPN ସେଟିଙ୍ଗ ବଦଳାନ୍ତୁ"</string>
+ <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"VPN ସେଟିଂସ୍ ବଦଳାନ୍ତୁ"</string>
<string name="configure" msgid="4905518375574791375">"କନଫିଗର୍ କରନ୍ତୁ"</string>
<string name="disconnect" msgid="971412338304200056">"ବିଚ୍ଛିନ୍ନ କରନ୍ତୁ"</string>
<string name="open_app" msgid="3717639178595958667">"ଆପ୍ ଖୋଲନ୍ତୁ"</string>
diff --git a/packages/VpnDialogs/res/values-pa/strings.xml b/packages/VpnDialogs/res/values-pa/strings.xml
index 1815f4f..d2eba0f 100644
--- a/packages/VpnDialogs/res/values-pa/strings.xml
+++ b/packages/VpnDialogs/res/values-pa/strings.xml
@@ -18,6 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"ਕਨੈਕਸ਼ਨ ਬੇਨਤੀ"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> ਇੱਕ VPN ਕਨੈਕਸ਼ਨ ਸੈਟ ਅਪ ਕਰਨਾ ਚਾਹੁੰਦਾ ਹੈ ਜੋ ਇਸਨੂੰ ਨੈੱਟਵਰਕ ਟ੍ਰੈਫਿਕ ਦਾ ਨਿਰੀਖਣ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਕੇਵਲ ਤਾਂ ਹੀ ਸਵੀਕਾਰ ਕਰੋ ਜੇਕਰ ਤੁਸੀਂ ਸਰੋਤ ਤੇ ਭਰੋਸਾ ਕਰਦੇ ਹੋ। <br /> <br /> <img src=vpn_icon /> ਤੁਹਾਡੀ ਸਕ੍ਰੀਨ ਦੇ ਟੌਪ ਤੇ ਪ੍ਰਗਟ ਹੁੰਦਾ ਹੈ ਜਦੋਂ VPN ਸਕਿਰਿਆ ਹੁੰਦਾ ਹੈ।"</string>
+ <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> ਕਿਸੇ ਅਜਿਹੇ VPN ਕਨੈਕਸ਼ਨ ਦਾ ਸੈੱਟਅੱਪ ਕਰਨਾ ਚਾਹੁੰਦੀ ਹੈ ਜੋ ਇਸਨੂੰ ਨੈੱਟਵਰਕ ਟਰੈਫ਼ਿਕ ਦੀ ਨਿਗਰਾਨੀ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਦਿੰਦਾ ਹੈ। ਸਿਰਫ਼ ਉਦੋਂ ਹੀ ਸਵੀਕਾਰ ਕਰੋ ਜੇ ਤੁਹਾਨੂੰ ਸਰੋਤ \'ਤੇ ਭਰੋਸਾ ਹੈ। VPN ਦੇ ਕਿਰਿਆਸ਼ੀਲ ਹੋਣ \'ਤੇ <br /> <br /> <img src=vpn_icon /> ਤੁਹਾਡੀ ਸਕ੍ਰੀਨ \'ਤੇ ਦਿਸਦਾ ਹੈ।"</string>
<string name="legacy_title" msgid="192936250066580964">"VPN ਕਨੈਕਟ ਕੀਤਾ ਗਿਆ ਹੈ"</string>
<string name="session" msgid="6470628549473641030">"ਸੈਸ਼ਨ:"</string>
<string name="duration" msgid="3584782459928719435">"ਮਿਆਦ:"</string>
diff --git a/packages/VpnDialogs/res/values-pl/strings.xml b/packages/VpnDialogs/res/values-pl/strings.xml
index d5201d7..bbcbaaf 100644
--- a/packages/VpnDialogs/res/values-pl/strings.xml
+++ b/packages/VpnDialogs/res/values-pl/strings.xml
@@ -18,6 +18,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Żądanie połączenia"</string>
<string name="warning" msgid="809658604548412033">"Aplikacja <xliff:g id="APP">%s</xliff:g> chce utworzyć połączenie VPN, które pozwoli jej na monitorowanie ruchu sieciowego. Zaakceptuj, tylko jeśli masz zaufanie do źródła. <br /> <br />Gdy sieć VPN jest aktywna, u góry ekranu pojawia się <img src=vpn_icon />."</string>
+ <!-- no translation found for warning (5188957997628124947) -->
+ <skip />
<string name="legacy_title" msgid="192936250066580964">"Połączono z VPN"</string>
<string name="session" msgid="6470628549473641030">"Sesja:"</string>
<string name="duration" msgid="3584782459928719435">"Czas trwania:"</string>
diff --git a/packages/VpnDialogs/res/values-pt-rBR/strings.xml b/packages/VpnDialogs/res/values-pt-rBR/strings.xml
index 75c1406..0d6dd0b 100644
--- a/packages/VpnDialogs/res/values-pt-rBR/strings.xml
+++ b/packages/VpnDialogs/res/values-pt-rBR/strings.xml
@@ -18,6 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Solicitação de conexão"</string>
<string name="warning" msgid="809658604548412033">"O <xliff:g id="APP">%s</xliff:g> quer configurar uma conexão VPN que permite monitorar o tráfego da rede. Aceite somente se confiar na origem. <br /> <br /> <img src=vpn_icon /> é exibido na parte superior da tela quando a rede VPN estiver ativa."</string>
+ <string name="warning" product="tv" msgid="5188957997628124947">"O app <xliff:g id="APP">%s</xliff:g> quer definir uma conexão VPN para monitorar o tráfego da rede. Aceite apenas se você confiar na fonte. O ícone <br /> <br /> <img src=vpn_icon /> aparecerá na tela quando a VPN estiver ativa."</string>
<string name="legacy_title" msgid="192936250066580964">"O VPN está conectado"</string>
<string name="session" msgid="6470628549473641030">"Sessão:"</string>
<string name="duration" msgid="3584782459928719435">"Duração:"</string>
diff --git a/packages/VpnDialogs/res/values-pt-rPT/strings.xml b/packages/VpnDialogs/res/values-pt-rPT/strings.xml
index 01beddb..a310104 100644
--- a/packages/VpnDialogs/res/values-pt-rPT/strings.xml
+++ b/packages/VpnDialogs/res/values-pt-rPT/strings.xml
@@ -18,6 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Pedido de ligação"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> pretende configurar uma ligação VPN que lhe permita monitorizar o tráfego de rede. Aceite apenas se confiar na fonte. <br /> <br /> <img src=vpn_icon /> aparece na parte superior do seu ecrã quando a VPN está ativa."</string>
+ <string name="warning" product="tv" msgid="5188957997628124947">"A app <xliff:g id="APP">%s</xliff:g> pretende configurar uma ligação VPN que lhe permita monitorizar o tráfego de rede. Aceite apenas se confiar na origem. <br /> <br /> <img src=vpn_icon /> aparece no ecrã quando a VPN está ativa."</string>
<string name="legacy_title" msgid="192936250066580964">"A VPN está ligada"</string>
<string name="session" msgid="6470628549473641030">"Sessão"</string>
<string name="duration" msgid="3584782459928719435">"Duração:"</string>
@@ -25,12 +26,12 @@
<string name="data_received" msgid="4062776929376067820">"Recebidos:"</string>
<string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> bytes / <xliff:g id="NUMBER_1">%2$s</xliff:g> pacotes"</string>
<string name="always_on_disconnected_title" msgid="1906740176262776166">"Não é possível estabelecer ligação à VPN sempre ativada"</string>
- <string name="always_on_disconnected_message" msgid="555634519845992917">"A aplicação <xliff:g id="VPN_APP_0">%1$s</xliff:g> está configurada para se manter sempre ligada, mas, neste momento, não é possível estabelecer ligação. O seu telemóvel irá utilizar uma rede pública até conseguir restabelecer ligação à aplicação <xliff:g id="VPN_APP_1">%1$s</xliff:g>."</string>
- <string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"A aplicação <xliff:g id="VPN_APP">%1$s</xliff:g> está configurada para se manter sempre ligada, mas, neste momento, não é possível estabelecer ligação. Não terá ligação até que a VPN a consiga restabelecer."</string>
+ <string name="always_on_disconnected_message" msgid="555634519845992917">"A app <xliff:g id="VPN_APP_0">%1$s</xliff:g> está configurada para se manter sempre ligada, mas, neste momento, não é possível estabelecer ligação. O seu telemóvel irá utilizar uma rede pública até conseguir restabelecer ligação à app <xliff:g id="VPN_APP_1">%1$s</xliff:g>."</string>
+ <string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"A app <xliff:g id="VPN_APP">%1$s</xliff:g> está configurada para se manter sempre ligada, mas, neste momento, não é possível estabelecer ligação. Não terá ligação até que a VPN a consiga restabelecer."</string>
<string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string>
<string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"Alterar as definições da VPN"</string>
<string name="configure" msgid="4905518375574791375">"Configurar"</string>
<string name="disconnect" msgid="971412338304200056">"Desligar"</string>
- <string name="open_app" msgid="3717639178595958667">"Abrir aplicação"</string>
+ <string name="open_app" msgid="3717639178595958667">"Abrir app"</string>
<string name="dismiss" msgid="6192859333764711227">"Ignorar"</string>
</resources>
diff --git a/packages/VpnDialogs/res/values-pt/strings.xml b/packages/VpnDialogs/res/values-pt/strings.xml
index 75c1406..0d6dd0b 100644
--- a/packages/VpnDialogs/res/values-pt/strings.xml
+++ b/packages/VpnDialogs/res/values-pt/strings.xml
@@ -18,6 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Solicitação de conexão"</string>
<string name="warning" msgid="809658604548412033">"O <xliff:g id="APP">%s</xliff:g> quer configurar uma conexão VPN que permite monitorar o tráfego da rede. Aceite somente se confiar na origem. <br /> <br /> <img src=vpn_icon /> é exibido na parte superior da tela quando a rede VPN estiver ativa."</string>
+ <string name="warning" product="tv" msgid="5188957997628124947">"O app <xliff:g id="APP">%s</xliff:g> quer definir uma conexão VPN para monitorar o tráfego da rede. Aceite apenas se você confiar na fonte. O ícone <br /> <br /> <img src=vpn_icon /> aparecerá na tela quando a VPN estiver ativa."</string>
<string name="legacy_title" msgid="192936250066580964">"O VPN está conectado"</string>
<string name="session" msgid="6470628549473641030">"Sessão:"</string>
<string name="duration" msgid="3584782459928719435">"Duração:"</string>
diff --git a/packages/VpnDialogs/res/values-ro/strings.xml b/packages/VpnDialogs/res/values-ro/strings.xml
index 4e60df2..5bda87e 100644
--- a/packages/VpnDialogs/res/values-ro/strings.xml
+++ b/packages/VpnDialogs/res/values-ro/strings.xml
@@ -18,6 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Solicitare de conexiune"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> dorește să configureze o conexiune VPN care să îi permită să monitorizeze traficul în rețea. Acceptați numai dacă aveți încredere în sursă. Atunci când conexiunea VPN este activă, <br /> <br /> <img src=vpn_icon /> se afișează în partea de sus a ecranului."</string>
+ <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> solicită permisiunea de a configura o conexiune VPN care să îi permită să monitorizeze traficul de rețea. Acceptați numai dacă aveți încredere în sursă. <br /> <br /> <img src=vpn_icon /> va apărea pe ecran atunci când conexiunea VPN este activă."</string>
<string name="legacy_title" msgid="192936250066580964">"VPN este conectat"</string>
<string name="session" msgid="6470628549473641030">"Sesiune:"</string>
<string name="duration" msgid="3584782459928719435">"Durată:"</string>
diff --git a/packages/VpnDialogs/res/values-ru/strings.xml b/packages/VpnDialogs/res/values-ru/strings.xml
index f8fcfb8..ce099562 100644
--- a/packages/VpnDialogs/res/values-ru/strings.xml
+++ b/packages/VpnDialogs/res/values-ru/strings.xml
@@ -18,6 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Запрос на подключение"</string>
<string name="warning" msgid="809658604548412033">"Приложение \"<xliff:g id="APP">%s</xliff:g>\" пытается подключиться к сети VPN, чтобы отслеживать трафик. Этот запрос следует принимать, только если вы доверяете источнику. <br /><br />Когда подключение к сети VPN активно, в верхней части экрана появляется значок <img src=vpn_icon />."</string>
+ <string name="warning" product="tv" msgid="5188957997628124947">"Приложение \"<xliff:g id="APP">%s</xliff:g>\" пытается подключиться к сети VPN, чтобы отслеживать трафик. Этот запрос следует принимать, только если вы доверяете источнику. Когда подключение к сети VPN активно, на экране появляется значок <br /> <br /> <img src=vpn_icon />."</string>
<string name="legacy_title" msgid="192936250066580964">"VPN-подключение установлено"</string>
<string name="session" msgid="6470628549473641030">"Сеанс:"</string>
<string name="duration" msgid="3584782459928719435">"Продолжительность:"</string>
diff --git a/packages/VpnDialogs/res/values-si/strings.xml b/packages/VpnDialogs/res/values-si/strings.xml
index bb97a5d..a836bae 100644
--- a/packages/VpnDialogs/res/values-si/strings.xml
+++ b/packages/VpnDialogs/res/values-si/strings.xml
@@ -18,6 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"සම්බන්ධතා ඉල්ලීම"</string>
<string name="warning" msgid="809658604548412033">"ජාල තදබදය නිරීක්ෂණය කිරීමට ඉඩ දෙන VPN සම්බන්ධතාවක් සැකසීමට <xliff:g id="APP">%s</xliff:g> අවශ්යය වේ. ප්රභවය ඔබ විශ්වාස කරන්නේ නම් පමණක් පිළිගන්න. VPN සක්රිය විට <br /> <br /> <img src=vpn_icon />."</string>
+ <string name="warning" product="tv" msgid="5188957997628124947">"ජාල තදබදය නිරීක්ෂණය කිරීමට ඉඩ දෙන VPN සම්බන්ධතාවක් සැකසීමට <xliff:g id="APP">%s</xliff:g> හට අවශ්ය වේ. ඔබ මූලාශ්රය විශ්වාස කරන්නේ නම් පමණක් පිළිගන්න. <br /> <br /> <img src=vpn_icon /> VPN සක්රිය විට ඔබගේ තිරයෙහි දිස් වේ."</string>
<string name="legacy_title" msgid="192936250066580964">"VPN සම්බන්ධිතයි"</string>
<string name="session" msgid="6470628549473641030">"සැසිය:"</string>
<string name="duration" msgid="3584782459928719435">"කාල සීමාව:"</string>
diff --git a/packages/VpnDialogs/res/values-sk/strings.xml b/packages/VpnDialogs/res/values-sk/strings.xml
index a08117a..766c139 100644
--- a/packages/VpnDialogs/res/values-sk/strings.xml
+++ b/packages/VpnDialogs/res/values-sk/strings.xml
@@ -18,6 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Žiadosť o pripojenie"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> žiada o nastavenie pripojenia VPN, pomocou ktorého bude môcť sledovať sieťové prenosy. Povoľte iba v prípade, že zdroju dôverujete. <br /> <br /> <img src=vpn_icon /> sa zobrazuje v hornej časti obrazovky, keď je pripojenie VPN aktívne."</string>
+ <string name="warning" product="tv" msgid="5188957997628124947">"Aplikácia <xliff:g id="APP">%s</xliff:g> chce nastaviť pripojenie k sieti VPN, ktoré jej umožňuje sledovať sieťovú premávku. Povoľte to iba v prípade, ak zdroju dôverujete. <br /> <br /> Keď je sieť VPN aktívna, na obrazovke sa zobrazí ikona <img src=vpn_icon />."</string>
<string name="legacy_title" msgid="192936250066580964">"Sieť VPN je pripojená"</string>
<string name="session" msgid="6470628549473641030">"Relácia"</string>
<string name="duration" msgid="3584782459928719435">"Trvanie:"</string>
diff --git a/packages/VpnDialogs/res/values-sl/strings.xml b/packages/VpnDialogs/res/values-sl/strings.xml
index d5014fa34..0b3fd93 100644
--- a/packages/VpnDialogs/res/values-sl/strings.xml
+++ b/packages/VpnDialogs/res/values-sl/strings.xml
@@ -18,6 +18,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Zahteva za povezavo"</string>
<string name="warning" msgid="809658604548412033">"Aplikacija <xliff:g id="APP">%s</xliff:g> želi nastaviti povezavo VPN, ki omogoča nadzor omrežnega prometa. To sprejmite samo, če zaupate viru. Ko je povezava VPN aktivna, se na vrhu zaslona prikaže ikona <br /> <br /> <img src=vpn_icon />."</string>
+ <!-- no translation found for warning (5188957997628124947) -->
+ <skip />
<string name="legacy_title" msgid="192936250066580964">"Povezava z navideznim zasebnim omrežjem je vzpostavljena"</string>
<string name="session" msgid="6470628549473641030">"Seja:"</string>
<string name="duration" msgid="3584782459928719435">"Trajanje:"</string>
diff --git a/packages/VpnDialogs/res/values-sq/strings.xml b/packages/VpnDialogs/res/values-sq/strings.xml
index 4a96e7b..f2cccbc 100644
--- a/packages/VpnDialogs/res/values-sq/strings.xml
+++ b/packages/VpnDialogs/res/values-sq/strings.xml
@@ -18,6 +18,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Kërkesë për lidhje"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> kërkon të vendosë një lidhje VPN-je që e lejon të monitorojë trafikun e rrjetit. Prano vetëm nëse i beson burimit. <br /> <br /> <img src=vpn_icon /> shfaqet në krye të ekranit kur VPN-ja është aktive."</string>
+ <!-- no translation found for warning (5188957997628124947) -->
+ <skip />
<string name="legacy_title" msgid="192936250066580964">"VPN-ja është e lidhur"</string>
<string name="session" msgid="6470628549473641030">"Sesioni:"</string>
<string name="duration" msgid="3584782459928719435">"Kohëzgjatja:"</string>
diff --git a/packages/VpnDialogs/res/values-sr/strings.xml b/packages/VpnDialogs/res/values-sr/strings.xml
index 8ce8060..01bd4df 100644
--- a/packages/VpnDialogs/res/values-sr/strings.xml
+++ b/packages/VpnDialogs/res/values-sr/strings.xml
@@ -18,6 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Захтев за повезивање"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> жели да подеси VPN везу која омогућава праћење саобраћаја на мрежи. Прихватите само ако верујете извору. <br /> <br /> <img src=vpn_icon /> се приказује у врху екрана када је VPN активан."</string>
+ <string name="warning" product="tv" msgid="5188957997628124947">"Апликација <xliff:g id="APP">%s</xliff:g> жели да подеси VPN везу која јој омогућава да прати мрежни саобраћај. Прихватите ово само ако имате поверења у извор. <br /> <br /> <img src=vpn_icon /> се приказује на екрану када је VPN активан."</string>
<string name="legacy_title" msgid="192936250066580964">"VPN је повезан"</string>
<string name="session" msgid="6470628549473641030">"Сесија:"</string>
<string name="duration" msgid="3584782459928719435">"Трајање:"</string>
diff --git a/packages/VpnDialogs/res/values-sv/strings.xml b/packages/VpnDialogs/res/values-sv/strings.xml
index 16b6a31..6c608a5 100644
--- a/packages/VpnDialogs/res/values-sv/strings.xml
+++ b/packages/VpnDialogs/res/values-sv/strings.xml
@@ -18,6 +18,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Anslutningsförfrågan"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> vill starta en VPN-anslutning som tillåter att appen övervakar nätverkstrafiken. Godkänn endast detta om du litar på källan. <br /> <br /> <img src=vpn_icon /> visas längst upp på skärmen när VPN-anslutningen är aktiv."</string>
+ <!-- no translation found for warning (5188957997628124947) -->
+ <skip />
<string name="legacy_title" msgid="192936250066580964">"VPN är anslutet"</string>
<string name="session" msgid="6470628549473641030">"Session:"</string>
<string name="duration" msgid="3584782459928719435">"Längd:"</string>
diff --git a/packages/VpnDialogs/res/values-sw/strings.xml b/packages/VpnDialogs/res/values-sw/strings.xml
index ea26884..c4f4662 100644
--- a/packages/VpnDialogs/res/values-sw/strings.xml
+++ b/packages/VpnDialogs/res/values-sw/strings.xml
@@ -18,6 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Ombi la muunganisho"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> inataka kusanidi muunganisho wa VPN utakaoiruhusu kufuatilia shughuli kwenye mtandao. Kubali ikiwa tu unakiamini chanzo. <br /> <br /> <img src=vpn_icon /> huonekana sehemu ya juu ya skrini yako VPN inapofanya kazi."</string>
+ <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> inagependa kuweka mipangilio ya muunganisho wa VPN inayoiruhusu kufuatilia trafiki ya mtandao. Kubali tu iwapo unaamini chanzo. <br /> <br /> <img src=vpn_icon /> huonekana kwenye skrini yako VPN inapotumika."</string>
<string name="legacy_title" msgid="192936250066580964">"VPN imeunganishwa"</string>
<string name="session" msgid="6470628549473641030">"Kipindi:"</string>
<string name="duration" msgid="3584782459928719435">"Muda:"</string>
diff --git a/packages/VpnDialogs/res/values-ta/strings.xml b/packages/VpnDialogs/res/values-ta/strings.xml
index 3b4cc57..73eae20 100644
--- a/packages/VpnDialogs/res/values-ta/strings.xml
+++ b/packages/VpnDialogs/res/values-ta/strings.xml
@@ -18,6 +18,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"இணைப்புக் கோரிக்கை"</string>
<string name="warning" msgid="809658604548412033">"நெட்வொர்க் டிராஃபிக்கைக் கண்காணிக்க வசதியாக VPN இணைப்பை அமைக்க <xliff:g id="APP">%s</xliff:g> கோருகிறது. நம்பகமான மூலத்தை மட்டுமே ஏற்கவும். <br /> <br /> VPN இயக்கத்தில் உள்ளபோது திரையின் மேல் பகுதியில் <img src=vpn_icon /> தோன்றும்."</string>
+ <!-- no translation found for warning (5188957997628124947) -->
+ <skip />
<string name="legacy_title" msgid="192936250066580964">"VPN இணைக்கப்பட்டது"</string>
<string name="session" msgid="6470628549473641030">"அமர்வு:"</string>
<string name="duration" msgid="3584782459928719435">"காலஅளவு:"</string>
diff --git a/packages/VpnDialogs/res/values-te/strings.xml b/packages/VpnDialogs/res/values-te/strings.xml
index 864c926..f6d19ff 100644
--- a/packages/VpnDialogs/res/values-te/strings.xml
+++ b/packages/VpnDialogs/res/values-te/strings.xml
@@ -18,6 +18,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"కనెక్షన్ అభ్యర్థన"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> నెట్వర్క్ ట్రాఫిక్ని పర్యవేక్షించగలగడానికి VPN కనెక్షన్ను సెటప్ చేయాలనుకుంటోంది. మీరు మూలాన్ని విశ్వసిస్తే మాత్రమే ఆమోదించండి. VPN సక్రియంగా ఉన్నప్పుడు మీ స్క్రీన్ ఎగువన <br /> <br /> <img src=vpn_icon /> కనిపిస్తుంది."</string>
+ <!-- no translation found for warning (5188957997628124947) -->
+ <skip />
<string name="legacy_title" msgid="192936250066580964">"VPN కనెక్ట్ చేయబడింది"</string>
<string name="session" msgid="6470628549473641030">"సెషన్:"</string>
<string name="duration" msgid="3584782459928719435">"వ్యవధి:"</string>
diff --git a/packages/VpnDialogs/res/values-th/strings.xml b/packages/VpnDialogs/res/values-th/strings.xml
index 333ff5f..2e174cd 100644
--- a/packages/VpnDialogs/res/values-th/strings.xml
+++ b/packages/VpnDialogs/res/values-th/strings.xml
@@ -18,6 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"ขอการเชื่อมต่อ"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> ต้องการสร้างการเชื่อมต่อ VPN เพื่อให้แอปสามารถตรวจสอบการเข้าใช้งานเครือข่าย โปรดยอมรับหากคุณเชื่อถือแหล่งที่มานี้เท่านั้น <br /> <br /> <img src=vpn_icon /> จะปรากฏที่ด้านบนหน้าจอเมื่อมีการใช้งาน VPN อยู่"</string>
+ <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> ต้องการตั้งค่าการเชื่อมต่อ VPN เพื่อให้ตรวจสอบการจราจรของข้อมูลในเครือข่ายได้ ยอมรับต่อเมื่อคุณไว้วางใจแหล่งที่มานี้เท่านั้น <br /> <br /> <img src=vpn_icon /> จะปรากฏบนหน้าจอเมื่อใช้งาน VPN อยู่"</string>
<string name="legacy_title" msgid="192936250066580964">"เชื่อมต่อ VPN แล้ว"</string>
<string name="session" msgid="6470628549473641030">"เซสชัน"</string>
<string name="duration" msgid="3584782459928719435">"ระยะเวลา:"</string>
diff --git a/packages/VpnDialogs/res/values-tl/strings.xml b/packages/VpnDialogs/res/values-tl/strings.xml
index 9c01c32..ea69fba 100644
--- a/packages/VpnDialogs/res/values-tl/strings.xml
+++ b/packages/VpnDialogs/res/values-tl/strings.xml
@@ -18,6 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Kahilingan sa koneksyon"</string>
<string name="warning" msgid="809658604548412033">"Gusto ng <xliff:g id="APP">%s</xliff:g> na mag-set up ng koneksyon sa VPN na nagbibigay-daan ditong masubaybayan ang trapiko ng network. Tanggapin lang kung pinagkakatiwalaan mo ang pinagmulan. Lalabas ang <br /> <br /> <img src=vpn_icon /> sa itaas ng iyong screen kapag aktibo ang VPN."</string>
+ <string name="warning" product="tv" msgid="5188957997628124947">"Gusto ng <xliff:g id="APP">%s</xliff:g> na mag-set up ng koneksyon sa VPN na nagbibigay-daan ditong masubaybayan ang trapiko sa network. Tanggapin lang kung pinagkakatiwalaan mo ang pinagmulan. Lalabas ang <br /> <br /> <img src=vpn_icon /> sa iyong screen kapag aktibo ang VPN."</string>
<string name="legacy_title" msgid="192936250066580964">"Nakakonekta ang VPN"</string>
<string name="session" msgid="6470628549473641030">"Session:"</string>
<string name="duration" msgid="3584782459928719435">"Tagal:"</string>
diff --git a/packages/VpnDialogs/res/values-tr/strings.xml b/packages/VpnDialogs/res/values-tr/strings.xml
index 8665a47..7ffa4bc 100644
--- a/packages/VpnDialogs/res/values-tr/strings.xml
+++ b/packages/VpnDialogs/res/values-tr/strings.xml
@@ -18,6 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Bağlantı isteği"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> ağ trafiğini izlemesine olanak veren bir VPN bağlantısı oluşturmak istiyor. Sadece, ilgili kaynağa güveniyorsanız kabul edin. <br /> <br /> VPN aktif olduğunda ekranınızın üst tarafında <img src=vpn_icon /> simgesi görünür."</string>
+ <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g>, ağ trafiğini izlemesine izin veren bir VPN bağlantısı oluşturmak istiyor. Yalnızca kaynağa güveniyorsanız kabul edin. VPN etkin olduğunda ekranınızda <br /> <br /> <img src=vpn_icon /> görünür."</string>
<string name="legacy_title" msgid="192936250066580964">"VPN bağlı"</string>
<string name="session" msgid="6470628549473641030">"Oturum:"</string>
<string name="duration" msgid="3584782459928719435">"Süre:"</string>
diff --git a/packages/VpnDialogs/res/values-uk/strings.xml b/packages/VpnDialogs/res/values-uk/strings.xml
index 8f91abf..6411d7c 100644
--- a/packages/VpnDialogs/res/values-uk/strings.xml
+++ b/packages/VpnDialogs/res/values-uk/strings.xml
@@ -18,6 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Запит на під’єднання"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> хоче під’єднатися до мережі VPN, щоб контролювати мережевий трафік. Дозволяйте, якщо довіряєте джерелу. Коли мережа VPN активна, угорі екрана відображається значок <br /> <br /> <img src=vpn_icon />."</string>
+ <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> хоче під’єднатися до мережі VPN, щоб контролювати мережевий трафік. Надавайте дозвіл, лише якщо довіряєте джерелу. Коли мережа VPN активна, на екрані з’являється значок <br /> <br /> <img src=vpn_icon />."</string>
<string name="legacy_title" msgid="192936250066580964">"Мережу VPN під’єднано"</string>
<string name="session" msgid="6470628549473641030">"Сеанс:"</string>
<string name="duration" msgid="3584782459928719435">"Тривалість:"</string>
diff --git a/packages/VpnDialogs/res/values-ur/strings.xml b/packages/VpnDialogs/res/values-ur/strings.xml
index db0c297..10dc56c 100644
--- a/packages/VpnDialogs/res/values-ur/strings.xml
+++ b/packages/VpnDialogs/res/values-ur/strings.xml
@@ -18,6 +18,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"کنکشن کی درخواست"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> ایک ایسا VPN کنکشن ترتیب دینا چاہتی ہے جو اسے نیٹ ورک ٹریفک کو مانیٹر کرنے کی اجازت دیتا ہے۔ اگر آپ کو ماخذ پر بھروسہ ہے تبھی قبول کریں۔ <br /> <br /> <img src=vpn_icon /> آپ کی اسکرین کے اوپر اس وقت ظاہر ہوتا ہے جب VPN فعال ہوتا ہے۔"</string>
+ <!-- no translation found for warning (5188957997628124947) -->
+ <skip />
<string name="legacy_title" msgid="192936250066580964">"VPN مربوط ہے"</string>
<string name="session" msgid="6470628549473641030">"سیشن:"</string>
<string name="duration" msgid="3584782459928719435">"دورانیہ:"</string>
diff --git a/packages/VpnDialogs/res/values-uz/strings.xml b/packages/VpnDialogs/res/values-uz/strings.xml
index 5a348a0..a3256e7 100644
--- a/packages/VpnDialogs/res/values-uz/strings.xml
+++ b/packages/VpnDialogs/res/values-uz/strings.xml
@@ -18,6 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Ulanish uchun so‘rov"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> ilovasi trafikni kuzatish uchun VPN tarmog‘iga ulanmoqchi. Agar ilovaga ishonsangiz, so‘rovga rozi bo‘ling.<br /> <br />VPN faol bo‘lsa, ekranning yuqori qismida <img src=vpn_icon /> belgisi paydo bo‘ladi."</string>
+ <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> ilovasi tarmoqdagi trafikni kuzatish uchun VPN aloqasini sozlamoqchi. Agar unga ishonsangiz, ruxsat bering. VPN aloqa faolligida ekranda <br /> <br /> <img src=vpn_icon /> chiqadi."</string>
<string name="legacy_title" msgid="192936250066580964">"VPN ulangan"</string>
<string name="session" msgid="6470628549473641030">"Seans:"</string>
<string name="duration" msgid="3584782459928719435">"Davomiyligi:"</string>
diff --git a/packages/VpnDialogs/res/values-vi/strings.xml b/packages/VpnDialogs/res/values-vi/strings.xml
index 097c9ae..ed338aa 100644
--- a/packages/VpnDialogs/res/values-vi/strings.xml
+++ b/packages/VpnDialogs/res/values-vi/strings.xml
@@ -18,6 +18,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Yêu cầu kết nối"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> muốn thiết lập kết nối VPN cho phép ứng dụng giám sát lưu lượng truy cập mạng. Chỉ chấp nhận nếu bạn tin tưởng nguồn. <br /> <br /> Biểu tượng <img src=vpn_icon /> xuất hiện ở đầu màn hình của bạn khi VPN đang hoạt động."</string>
+ <!-- no translation found for warning (5188957997628124947) -->
+ <skip />
<string name="legacy_title" msgid="192936250066580964">"VPN được kết nối"</string>
<string name="session" msgid="6470628549473641030">"Phiên"</string>
<string name="duration" msgid="3584782459928719435">"Thời lượng:"</string>
diff --git a/packages/VpnDialogs/res/values-zh-rCN/strings.xml b/packages/VpnDialogs/res/values-zh-rCN/strings.xml
index 7e528bd..6992d2e 100644
--- a/packages/VpnDialogs/res/values-zh-rCN/strings.xml
+++ b/packages/VpnDialogs/res/values-zh-rCN/strings.xml
@@ -18,6 +18,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"网络连接请求"</string>
<string name="warning" msgid="809658604548412033">"“<xliff:g id="APP">%s</xliff:g>”想要设置一个 VPN 连接,以便监控网络流量。除非您信任该来源,否则请勿接受此请求。<br /> <br />启用 VPN 后,屏幕顶部会出现一个 <img src=vpn_icon /> 图标。"</string>
+ <!-- no translation found for warning (5188957997628124947) -->
+ <skip />
<string name="legacy_title" msgid="192936250066580964">"已连接VPN"</string>
<string name="session" msgid="6470628549473641030">"会话:"</string>
<string name="duration" msgid="3584782459928719435">"时长:"</string>
diff --git a/packages/VpnDialogs/res/values-zh-rHK/strings.xml b/packages/VpnDialogs/res/values-zh-rHK/strings.xml
index 49605b0..e4e6432 100644
--- a/packages/VpnDialogs/res/values-zh-rHK/strings.xml
+++ b/packages/VpnDialogs/res/values-zh-rHK/strings.xml
@@ -18,6 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"連線要求"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> 要求設定 VPN 連線以監控網絡流量。除非您信任要求來源,否則請勿隨意接受要求。<br /> <br />VPN 啟用時,畫面頂端會顯示 <img src=vpn_icon />。"</string>
+ <string name="warning" product="tv" msgid="5188957997628124947">"「<xliff:g id="APP">%s</xliff:g>」要求設定 VPN 連線以監控網絡流量。除非您信任要求來源,否則請勿隨意接受要求。VPN 啟用時,畫面會顯示 <br /> <br /> <img src=vpn_icon />。"</string>
<string name="legacy_title" msgid="192936250066580964">"VPN 已連線"</string>
<string name="session" msgid="6470628549473641030">"時段:"</string>
<string name="duration" msgid="3584782459928719435">"持續時間︰"</string>
diff --git a/packages/VpnDialogs/res/values-zh-rTW/strings.xml b/packages/VpnDialogs/res/values-zh-rTW/strings.xml
index edd8e61..e704e03 100644
--- a/packages/VpnDialogs/res/values-zh-rTW/strings.xml
+++ b/packages/VpnDialogs/res/values-zh-rTW/strings.xml
@@ -18,6 +18,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"連線要求"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> 要求設定 VPN 連線,允許此要求即開放該來源監控網路流量。除非你信任該來源,否則請勿任意接受要求。<br /> <br />VPN 啟用時,畫面頂端會顯示 <img src=vpn_icon />。"</string>
+ <!-- no translation found for warning (5188957997628124947) -->
+ <skip />
<string name="legacy_title" msgid="192936250066580964">"VPN 已連線"</string>
<string name="session" msgid="6470628549473641030">"工作階段:"</string>
<string name="duration" msgid="3584782459928719435">"持續時間:"</string>
diff --git a/packages/VpnDialogs/res/values-zu/strings.xml b/packages/VpnDialogs/res/values-zu/strings.xml
index 4ab1225..ddfed40 100644
--- a/packages/VpnDialogs/res/values-zu/strings.xml
+++ b/packages/VpnDialogs/res/values-zu/strings.xml
@@ -18,6 +18,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Isicelo soxhumo"</string>
<string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> ifuna ukusetha uxhumo lwe-VPN eyivumela ukwengamela ithrafikhi yenethiwekhi. Yamukela kuphela uma wethemba umthombo. <br /> <br /> <img src=vpn_icon /> ibonakala phezu kwesikrini sakho uma i-VPN isebenza."</string>
+ <!-- no translation found for warning (5188957997628124947) -->
+ <skip />
<string name="legacy_title" msgid="192936250066580964">"I-VPN ixhunyiwe"</string>
<string name="session" msgid="6470628549473641030">"Iseshini:"</string>
<string name="duration" msgid="3584782459928719435">"Ubude besikhathi:"</string>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-af/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-af/strings.xml
new file mode 100644
index 0000000..8c47bcc
--- /dev/null
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-af/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Versteek (vermy programme in uitsnede-area)"</string>
+</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-am/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-am/strings.xml
new file mode 100644
index 0000000..0f1edf6
--- /dev/null
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-am/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"ደብቅ (በተቆራረጠ ክልል ውስጥ መተግበሪያዎችን ያስወግዱ)"</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
new file mode 100644
index 0000000..c21fcda
--- /dev/null
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-b+sr+Latn/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Sakrij (izbegavaj aplikacije u izrezanoj oblasti)"</string>
+</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-bg/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-bg/strings.xml
new file mode 100644
index 0000000..8b81d6a
--- /dev/null
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-bg/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Скриване (избягване на приложенията в областта на прореза на екрана)"</string>
+</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-bs/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-bs/strings.xml
new file mode 100644
index 0000000..eb2b8d2
--- /dev/null
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-bs/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Sakrij (izbjegavaj aplikacije u izrezanoj oblasti)"</string>
+</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-cs/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-cs/strings.xml
new file mode 100644
index 0000000..67ed6aff
--- /dev/null
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-cs/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Skrýt (nezobrazovat aplikace v oblasti výřezu)"</string>
+</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-da/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-da/strings.xml
new file mode 100644
index 0000000..dcf70bf
--- /dev/null
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-da/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Skjul (undgå apps i cutout-område)"</string>
+</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-de/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-de/strings.xml
new file mode 100644
index 0000000..86e3732
--- /dev/null
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-de/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Ausblenden (Apps im Bereich der Display-Aussparung vermeiden)"</string>
+</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-el/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-el/strings.xml
new file mode 100644
index 0000000..9806966
--- /dev/null
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-el/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Απόκρυψη (αποφυγή εφαρμογών στην περιοχή εγκοπής)"</string>
+</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-en-rAU/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-en-rAU/strings.xml
new file mode 100644
index 0000000..a7700b9
--- /dev/null
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-en-rAU/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Hide (avoid apps in cutout region)"</string>
+</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-en-rCA/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-en-rCA/strings.xml
new file mode 100644
index 0000000..a7700b9
--- /dev/null
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-en-rCA/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Hide (avoid apps in cutout region)"</string>
+</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-en-rGB/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-en-rGB/strings.xml
new file mode 100644
index 0000000..a7700b9
--- /dev/null
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-en-rGB/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Hide (avoid apps in cutout region)"</string>
+</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-en-rIN/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-en-rIN/strings.xml
new file mode 100644
index 0000000..a7700b9
--- /dev/null
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-en-rIN/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Hide (avoid apps in cutout region)"</string>
+</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-en-rXC/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-en-rXC/strings.xml
new file mode 100644
index 0000000..e9b76fb
--- /dev/null
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-en-rXC/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Hide (avoid apps in cutout region)"</string>
+</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-es-rUS/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-es-rUS/strings.xml
new file mode 100644
index 0000000..ee5f8ea
--- /dev/null
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-es-rUS/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Ocultar (evitar apps en la región excluida)"</string>
+</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-es/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-es/strings.xml
new file mode 100644
index 0000000..c244e49
--- /dev/null
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-es/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Ocultar (evitar aplicaciones en la zona recortada)"</string>
+</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-eu/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-eu/strings.xml
new file mode 100644
index 0000000..f1a6fda
--- /dev/null
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-eu/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Ezkutatu (saihestu aplikazioak agertzea pantailaren mozketa-eremuan)"</string>
+</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-fi/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-fi/strings.xml
new file mode 100644
index 0000000..5e626ee
--- /dev/null
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-fi/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Piilota (vältä lovialueella olevia sovelluksia)"</string>
+</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-fr-rCA/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-fr-rCA/strings.xml
new file mode 100644
index 0000000..5c9194e
--- /dev/null
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-fr-rCA/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Masquer (éviter les applications dans la forme découpée)"</string>
+</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-gl/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-gl/strings.xml
new file mode 100644
index 0000000..a05a5fd
--- /dev/null
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-gl/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Ocultar (non mostrar as aplicacións que aparezan na zona recortada)"</string>
+</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-hr/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-hr/strings.xml
new file mode 100644
index 0000000..a2c1feb
--- /dev/null
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-hr/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Sakrij (izbjegavaj aplikacije u području ureza)"</string>
+</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-in/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-in/strings.xml
new file mode 100644
index 0000000..d40d73b
--- /dev/null
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-in/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Sembunyikan (hindari aplikasi di wilayah cutout)"</string>
+</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-it/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-it/strings.xml
new file mode 100644
index 0000000..90b9810
--- /dev/null
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-it/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Nascondi (evita le app nell\'area di ritaglio)"</string>
+</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ja/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ja/strings.xml
new file mode 100644
index 0000000..69b9f24
--- /dev/null
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ja/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"非表示(カットアウト領域にアプリを表示しない)"</string>
+</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ka/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ka/strings.xml
new file mode 100644
index 0000000..1ee2fae
--- /dev/null
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ka/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"დამალვა (აპების არდაშვება ჭრილის უბანში)"</string>
+</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-km/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-km/strings.xml
new file mode 100644
index 0000000..ea0a9d0
--- /dev/null
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-km/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"លាក់ (ជៀសវាងបង្ហាញកម្មវិធីនៅផ្នែកឆក)"</string>
+</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ko/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ko/strings.xml
new file mode 100644
index 0000000..97856d3
--- /dev/null
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ko/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"숨기기(컷아웃 영역에 앱을 표시하지 않음)"</string>
+</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-lo/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-lo/strings.xml
new file mode 100644
index 0000000..29ec224
--- /dev/null
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-lo/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"ເຊື່ອງ (ຫຼີກເວັ້ນແອັບໃນພື້ນທີ່ຕັດອອກ)"</string>
+</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-mk/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-mk/strings.xml
new file mode 100644
index 0000000..67b45d3
--- /dev/null
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-mk/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Сокриј (избегнувај апликации во отсечен регион)"</string>
+</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-mn/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-mn/strings.xml
new file mode 100644
index 0000000..9bda419
--- /dev/null
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-mn/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Нуух (тусгаарласан бүс дэх аппуудаас зайлсхийнэ)"</string>
+</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ms/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ms/strings.xml
new file mode 100644
index 0000000..5864ff8
--- /dev/null
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ms/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Sembunyikan (elakkan apl dalam kawasan potongan)"</string>
+</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-nl/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-nl/strings.xml
new file mode 100644
index 0000000..0e51514
--- /dev/null
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-nl/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Verbergen (apps in cutout-regio vermijden)"</string>
+</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-pa/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-pa/strings.xml
new file mode 100644
index 0000000..803a69d
--- /dev/null
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-pa/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"ਲੁਕਾਓ (ਕੱਟਆਊਟ ਖੇਤਰ ਵਿਚਲੀਆਂ ਐਪਾਂ ਨੂੰ ਨਾ ਛੇੜੋ)"</string>
+</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-pt-rBR/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-pt-rBR/strings.xml
new file mode 100644
index 0000000..b5364e9
--- /dev/null
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-pt-rBR/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Ocultar (evitar apps na região recortada)"</string>
+</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-pt-rPT/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-pt-rPT/strings.xml
new file mode 100644
index 0000000..e9467a2
--- /dev/null
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-pt-rPT/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Ocultar (evitar apps na á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
new file mode 100644
index 0000000..b5364e9
--- /dev/null
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-pt/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Ocultar (evitar apps na região recortada)"</string>
+</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ro/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ro/strings.xml
new file mode 100644
index 0000000..9227ceb
--- /dev/null
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ro/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Ascundeți (evitați aplicațiile din regiunea decupată)"</string>
+</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ru/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ru/strings.xml
new file mode 100644
index 0000000..8335c77
--- /dev/null
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ru/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Скрыть (не показывать приложения в вырезе на экране)"</string>
+</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-si/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-si/strings.xml
new file mode 100644
index 0000000..d21b02c
--- /dev/null
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-si/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"සඟවන්න (කටවුට් කලාපයෙහි යෙදුම් වළක්වන්න)"</string>
+</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-sk/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-sk/strings.xml
new file mode 100644
index 0000000..dfd01af
--- /dev/null
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-sk/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Skryť (nezobrazovať aplikácie v oblasti výrezu)"</string>
+</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-sr/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-sr/strings.xml
new file mode 100644
index 0000000..c835b35
--- /dev/null
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-sr/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Сакриј (избегавај апликације у изрезаној области)"</string>
+</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-sw/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-sw/strings.xml
new file mode 100644
index 0000000..57ef684
--- /dev/null
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-sw/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Ficha (epuka programu katika eneo lenye pengo)"</string>
+</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-th/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-th/strings.xml
new file mode 100644
index 0000000..09d597d
--- /dev/null
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-th/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"ซ่อน (หลีกเลี่ยงการแสดงแอปในภูมิภาคที่ถูกตัดออก)"</string>
+</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-tl/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-tl/strings.xml
new file mode 100644
index 0000000..6b1c372
--- /dev/null
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-tl/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Itago (iwasan ang mga app sa rehiyon ng cutout)"</string>
+</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-tr/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-tr/strings.xml
new file mode 100644
index 0000000..991a840
--- /dev/null
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-tr/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Gizle (kesim bölgesindeki uygulamalardan kaçının)"</string>
+</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-uk/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-uk/strings.xml
new file mode 100644
index 0000000..7d6c068
--- /dev/null
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-uk/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Сховати (не показувати додатки з вирізаних регіонів)"</string>
+</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-uz/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-uz/strings.xml
new file mode 100644
index 0000000..13a56ac
--- /dev/null
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-uz/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"Berkitish (qirqilgan hudud ilovalariga diqqat qiling)"</string>
+</resources>
diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-zh-rHK/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-zh-rHK/strings.xml
new file mode 100644
index 0000000..7f37f3b
--- /dev/null
+++ b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-zh-rHK/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_cutout_emulation_overlay" msgid="1946296620328354129">"隱藏 (避免將應用程式置於凹口區域)"</string>
+</resources>
diff --git a/packages/SystemUI/res/drawable/circle_green_10dp.xml b/packages/overlays/NoCutoutOverlay/res/values-af/strings.xml
similarity index 61%
copy from packages/SystemUI/res/drawable/circle_green_10dp.xml
copy to packages/overlays/NoCutoutOverlay/res/values-af/strings.xml
index 571ec62..b021da7 100644
--- a/packages/SystemUI/res/drawable/circle_green_10dp.xml
+++ b/packages/overlays/NoCutoutOverlay/res/values-af/strings.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
+<?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.
@@ -13,10 +13,9 @@
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size android:height="10dp"
- android:width="10dp" />
- <solid android:color="#34A853" />
-</shape>
\ No newline at end of file
+ -->
+
+<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="9031691255599853162">"Versteek"</string>
+</resources>
diff --git a/packages/SystemUI/res/drawable/circle_green_10dp.xml b/packages/overlays/NoCutoutOverlay/res/values-am/strings.xml
similarity index 61%
copy from packages/SystemUI/res/drawable/circle_green_10dp.xml
copy to packages/overlays/NoCutoutOverlay/res/values-am/strings.xml
index 571ec62..0ca6135 100644
--- a/packages/SystemUI/res/drawable/circle_green_10dp.xml
+++ b/packages/overlays/NoCutoutOverlay/res/values-am/strings.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
+<?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.
@@ -13,10 +13,9 @@
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size android:height="10dp"
- android:width="10dp" />
- <solid android:color="#34A853" />
-</shape>
\ No newline at end of file
+ -->
+
+<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="9031691255599853162">"ደብቅ"</string>
+</resources>
diff --git a/packages/SystemUI/res/drawable/circle_green_10dp.xml b/packages/overlays/NoCutoutOverlay/res/values-b+sr+Latn/strings.xml
similarity index 61%
copy from packages/SystemUI/res/drawable/circle_green_10dp.xml
copy to packages/overlays/NoCutoutOverlay/res/values-b+sr+Latn/strings.xml
index 571ec62..082e586 100644
--- a/packages/SystemUI/res/drawable/circle_green_10dp.xml
+++ b/packages/overlays/NoCutoutOverlay/res/values-b+sr+Latn/strings.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
+<?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.
@@ -13,10 +13,9 @@
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size android:height="10dp"
- android:width="10dp" />
- <solid android:color="#34A853" />
-</shape>
\ No newline at end of file
+ -->
+
+<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="9031691255599853162">"Sakrij"</string>
+</resources>
diff --git a/packages/SystemUI/res/drawable/circle_green_10dp.xml b/packages/overlays/NoCutoutOverlay/res/values-bg/strings.xml
similarity index 61%
copy from packages/SystemUI/res/drawable/circle_green_10dp.xml
copy to packages/overlays/NoCutoutOverlay/res/values-bg/strings.xml
index 571ec62..7c3170c 100644
--- a/packages/SystemUI/res/drawable/circle_green_10dp.xml
+++ b/packages/overlays/NoCutoutOverlay/res/values-bg/strings.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
+<?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.
@@ -13,10 +13,9 @@
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size android:height="10dp"
- android:width="10dp" />
- <solid android:color="#34A853" />
-</shape>
\ No newline at end of file
+ -->
+
+<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="9031691255599853162">"Скриване"</string>
+</resources>
diff --git a/packages/SystemUI/res/drawable/circle_green_10dp.xml b/packages/overlays/NoCutoutOverlay/res/values-bs/strings.xml
similarity index 61%
copy from packages/SystemUI/res/drawable/circle_green_10dp.xml
copy to packages/overlays/NoCutoutOverlay/res/values-bs/strings.xml
index 571ec62..082e586 100644
--- a/packages/SystemUI/res/drawable/circle_green_10dp.xml
+++ b/packages/overlays/NoCutoutOverlay/res/values-bs/strings.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
+<?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.
@@ -13,10 +13,9 @@
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size android:height="10dp"
- android:width="10dp" />
- <solid android:color="#34A853" />
-</shape>
\ No newline at end of file
+ -->
+
+<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="9031691255599853162">"Sakrij"</string>
+</resources>
diff --git a/packages/SystemUI/res/drawable/circle_green_10dp.xml b/packages/overlays/NoCutoutOverlay/res/values-cs/strings.xml
similarity index 61%
copy from packages/SystemUI/res/drawable/circle_green_10dp.xml
copy to packages/overlays/NoCutoutOverlay/res/values-cs/strings.xml
index 571ec62..068bb94 100644
--- a/packages/SystemUI/res/drawable/circle_green_10dp.xml
+++ b/packages/overlays/NoCutoutOverlay/res/values-cs/strings.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
+<?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.
@@ -13,10 +13,9 @@
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size android:height="10dp"
- android:width="10dp" />
- <solid android:color="#34A853" />
-</shape>
\ No newline at end of file
+ -->
+
+<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="9031691255599853162">"Skrýt"</string>
+</resources>
diff --git a/packages/SystemUI/res/drawable/circle_green_10dp.xml b/packages/overlays/NoCutoutOverlay/res/values-da/strings.xml
similarity index 61%
copy from packages/SystemUI/res/drawable/circle_green_10dp.xml
copy to packages/overlays/NoCutoutOverlay/res/values-da/strings.xml
index 571ec62..6ecb767 100644
--- a/packages/SystemUI/res/drawable/circle_green_10dp.xml
+++ b/packages/overlays/NoCutoutOverlay/res/values-da/strings.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
+<?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.
@@ -13,10 +13,9 @@
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size android:height="10dp"
- android:width="10dp" />
- <solid android:color="#34A853" />
-</shape>
\ No newline at end of file
+ -->
+
+<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="9031691255599853162">"Skjul"</string>
+</resources>
diff --git a/packages/SystemUI/res/drawable/circle_green_10dp.xml b/packages/overlays/NoCutoutOverlay/res/values-de/strings.xml
similarity index 61%
copy from packages/SystemUI/res/drawable/circle_green_10dp.xml
copy to packages/overlays/NoCutoutOverlay/res/values-de/strings.xml
index 571ec62..44278e8 100644
--- a/packages/SystemUI/res/drawable/circle_green_10dp.xml
+++ b/packages/overlays/NoCutoutOverlay/res/values-de/strings.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
+<?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.
@@ -13,10 +13,9 @@
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size android:height="10dp"
- android:width="10dp" />
- <solid android:color="#34A853" />
-</shape>
\ No newline at end of file
+ -->
+
+<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="9031691255599853162">"Ausblenden"</string>
+</resources>
diff --git a/packages/SystemUI/res/drawable/circle_green_10dp.xml b/packages/overlays/NoCutoutOverlay/res/values-el/strings.xml
similarity index 61%
copy from packages/SystemUI/res/drawable/circle_green_10dp.xml
copy to packages/overlays/NoCutoutOverlay/res/values-el/strings.xml
index 571ec62..96b1b86 100644
--- a/packages/SystemUI/res/drawable/circle_green_10dp.xml
+++ b/packages/overlays/NoCutoutOverlay/res/values-el/strings.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
+<?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.
@@ -13,10 +13,9 @@
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size android:height="10dp"
- android:width="10dp" />
- <solid android:color="#34A853" />
-</shape>
\ No newline at end of file
+ -->
+
+<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="9031691255599853162">"Απόκρυψη"</string>
+</resources>
diff --git a/packages/SystemUI/res/drawable/circle_green_10dp.xml b/packages/overlays/NoCutoutOverlay/res/values-en-rAU/strings.xml
similarity index 61%
copy from packages/SystemUI/res/drawable/circle_green_10dp.xml
copy to packages/overlays/NoCutoutOverlay/res/values-en-rAU/strings.xml
index 571ec62..1ab9b2d 100644
--- a/packages/SystemUI/res/drawable/circle_green_10dp.xml
+++ b/packages/overlays/NoCutoutOverlay/res/values-en-rAU/strings.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
+<?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.
@@ -13,10 +13,9 @@
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size android:height="10dp"
- android:width="10dp" />
- <solid android:color="#34A853" />
-</shape>
\ No newline at end of file
+ -->
+
+<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="9031691255599853162">"Hide"</string>
+</resources>
diff --git a/packages/SystemUI/res/drawable/circle_green_10dp.xml b/packages/overlays/NoCutoutOverlay/res/values-en-rCA/strings.xml
similarity index 61%
copy from packages/SystemUI/res/drawable/circle_green_10dp.xml
copy to packages/overlays/NoCutoutOverlay/res/values-en-rCA/strings.xml
index 571ec62..1ab9b2d 100644
--- a/packages/SystemUI/res/drawable/circle_green_10dp.xml
+++ b/packages/overlays/NoCutoutOverlay/res/values-en-rCA/strings.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
+<?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.
@@ -13,10 +13,9 @@
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size android:height="10dp"
- android:width="10dp" />
- <solid android:color="#34A853" />
-</shape>
\ No newline at end of file
+ -->
+
+<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="9031691255599853162">"Hide"</string>
+</resources>
diff --git a/packages/SystemUI/res/drawable/circle_green_10dp.xml b/packages/overlays/NoCutoutOverlay/res/values-en-rGB/strings.xml
similarity index 61%
copy from packages/SystemUI/res/drawable/circle_green_10dp.xml
copy to packages/overlays/NoCutoutOverlay/res/values-en-rGB/strings.xml
index 571ec62..1ab9b2d 100644
--- a/packages/SystemUI/res/drawable/circle_green_10dp.xml
+++ b/packages/overlays/NoCutoutOverlay/res/values-en-rGB/strings.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
+<?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.
@@ -13,10 +13,9 @@
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size android:height="10dp"
- android:width="10dp" />
- <solid android:color="#34A853" />
-</shape>
\ No newline at end of file
+ -->
+
+<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="9031691255599853162">"Hide"</string>
+</resources>
diff --git a/packages/SystemUI/res/drawable/circle_green_10dp.xml b/packages/overlays/NoCutoutOverlay/res/values-en-rIN/strings.xml
similarity index 61%
copy from packages/SystemUI/res/drawable/circle_green_10dp.xml
copy to packages/overlays/NoCutoutOverlay/res/values-en-rIN/strings.xml
index 571ec62..1ab9b2d 100644
--- a/packages/SystemUI/res/drawable/circle_green_10dp.xml
+++ b/packages/overlays/NoCutoutOverlay/res/values-en-rIN/strings.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
+<?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.
@@ -13,10 +13,9 @@
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size android:height="10dp"
- android:width="10dp" />
- <solid android:color="#34A853" />
-</shape>
\ No newline at end of file
+ -->
+
+<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="9031691255599853162">"Hide"</string>
+</resources>
diff --git a/packages/overlays/NoCutoutOverlay/res/values-en-rXC/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-en-rXC/strings.xml
new file mode 100644
index 0000000..a20e594
--- /dev/null
+++ b/packages/overlays/NoCutoutOverlay/res/values-en-rXC/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Hide"</string>
+</resources>
diff --git a/packages/SystemUI/res/drawable/circle_green_10dp.xml b/packages/overlays/NoCutoutOverlay/res/values-es-rUS/strings.xml
similarity index 61%
copy from packages/SystemUI/res/drawable/circle_green_10dp.xml
copy to packages/overlays/NoCutoutOverlay/res/values-es-rUS/strings.xml
index 571ec62..351c1cd 100644
--- a/packages/SystemUI/res/drawable/circle_green_10dp.xml
+++ b/packages/overlays/NoCutoutOverlay/res/values-es-rUS/strings.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
+<?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.
@@ -13,10 +13,9 @@
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size android:height="10dp"
- android:width="10dp" />
- <solid android:color="#34A853" />
-</shape>
\ No newline at end of file
+ -->
+
+<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="9031691255599853162">"Ocultar"</string>
+</resources>
diff --git a/packages/SystemUI/res/drawable/circle_green_10dp.xml b/packages/overlays/NoCutoutOverlay/res/values-es/strings.xml
similarity index 61%
copy from packages/SystemUI/res/drawable/circle_green_10dp.xml
copy to packages/overlays/NoCutoutOverlay/res/values-es/strings.xml
index 571ec62..351c1cd 100644
--- a/packages/SystemUI/res/drawable/circle_green_10dp.xml
+++ b/packages/overlays/NoCutoutOverlay/res/values-es/strings.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
+<?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.
@@ -13,10 +13,9 @@
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size android:height="10dp"
- android:width="10dp" />
- <solid android:color="#34A853" />
-</shape>
\ No newline at end of file
+ -->
+
+<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="9031691255599853162">"Ocultar"</string>
+</resources>
diff --git a/packages/SystemUI/res/drawable/circle_green_10dp.xml b/packages/overlays/NoCutoutOverlay/res/values-eu/strings.xml
similarity index 61%
copy from packages/SystemUI/res/drawable/circle_green_10dp.xml
copy to packages/overlays/NoCutoutOverlay/res/values-eu/strings.xml
index 571ec62..f33bb50 100644
--- a/packages/SystemUI/res/drawable/circle_green_10dp.xml
+++ b/packages/overlays/NoCutoutOverlay/res/values-eu/strings.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
+<?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.
@@ -13,10 +13,9 @@
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size android:height="10dp"
- android:width="10dp" />
- <solid android:color="#34A853" />
-</shape>
\ No newline at end of file
+ -->
+
+<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="9031691255599853162">"Ezkutatu"</string>
+</resources>
diff --git a/packages/SystemUI/res/drawable/circle_green_10dp.xml b/packages/overlays/NoCutoutOverlay/res/values-fi/strings.xml
similarity index 61%
copy from packages/SystemUI/res/drawable/circle_green_10dp.xml
copy to packages/overlays/NoCutoutOverlay/res/values-fi/strings.xml
index 571ec62..c42e52d 100644
--- a/packages/SystemUI/res/drawable/circle_green_10dp.xml
+++ b/packages/overlays/NoCutoutOverlay/res/values-fi/strings.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
+<?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.
@@ -13,10 +13,9 @@
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size android:height="10dp"
- android:width="10dp" />
- <solid android:color="#34A853" />
-</shape>
\ No newline at end of file
+ -->
+
+<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="9031691255599853162">"Piilota"</string>
+</resources>
diff --git a/packages/SystemUI/res/drawable/circle_green_10dp.xml b/packages/overlays/NoCutoutOverlay/res/values-fr-rCA/strings.xml
similarity index 61%
copy from packages/SystemUI/res/drawable/circle_green_10dp.xml
copy to packages/overlays/NoCutoutOverlay/res/values-fr-rCA/strings.xml
index 571ec62..31fa567 100644
--- a/packages/SystemUI/res/drawable/circle_green_10dp.xml
+++ b/packages/overlays/NoCutoutOverlay/res/values-fr-rCA/strings.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
+<?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.
@@ -13,10 +13,9 @@
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size android:height="10dp"
- android:width="10dp" />
- <solid android:color="#34A853" />
-</shape>
\ No newline at end of file
+ -->
+
+<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="9031691255599853162">"Masquer"</string>
+</resources>
diff --git a/packages/SystemUI/res/drawable/circle_green_10dp.xml b/packages/overlays/NoCutoutOverlay/res/values-gl/strings.xml
similarity index 61%
copy from packages/SystemUI/res/drawable/circle_green_10dp.xml
copy to packages/overlays/NoCutoutOverlay/res/values-gl/strings.xml
index 571ec62..351c1cd 100644
--- a/packages/SystemUI/res/drawable/circle_green_10dp.xml
+++ b/packages/overlays/NoCutoutOverlay/res/values-gl/strings.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
+<?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.
@@ -13,10 +13,9 @@
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size android:height="10dp"
- android:width="10dp" />
- <solid android:color="#34A853" />
-</shape>
\ No newline at end of file
+ -->
+
+<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="9031691255599853162">"Ocultar"</string>
+</resources>
diff --git a/packages/SystemUI/res/drawable/circle_green_10dp.xml b/packages/overlays/NoCutoutOverlay/res/values-hr/strings.xml
similarity index 61%
copy from packages/SystemUI/res/drawable/circle_green_10dp.xml
copy to packages/overlays/NoCutoutOverlay/res/values-hr/strings.xml
index 571ec62..082e586 100644
--- a/packages/SystemUI/res/drawable/circle_green_10dp.xml
+++ b/packages/overlays/NoCutoutOverlay/res/values-hr/strings.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
+<?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.
@@ -13,10 +13,9 @@
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size android:height="10dp"
- android:width="10dp" />
- <solid android:color="#34A853" />
-</shape>
\ No newline at end of file
+ -->
+
+<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="9031691255599853162">"Sakrij"</string>
+</resources>
diff --git a/packages/SystemUI/res/drawable/circle_green_10dp.xml b/packages/overlays/NoCutoutOverlay/res/values-in/strings.xml
similarity index 61%
copy from packages/SystemUI/res/drawable/circle_green_10dp.xml
copy to packages/overlays/NoCutoutOverlay/res/values-in/strings.xml
index 571ec62..6c017b3 100644
--- a/packages/SystemUI/res/drawable/circle_green_10dp.xml
+++ b/packages/overlays/NoCutoutOverlay/res/values-in/strings.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
+<?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.
@@ -13,10 +13,9 @@
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size android:height="10dp"
- android:width="10dp" />
- <solid android:color="#34A853" />
-</shape>
\ No newline at end of file
+ -->
+
+<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="9031691255599853162">"Sembunyikan"</string>
+</resources>
diff --git a/packages/SystemUI/res/drawable/circle_green_10dp.xml b/packages/overlays/NoCutoutOverlay/res/values-it/strings.xml
similarity index 61%
copy from packages/SystemUI/res/drawable/circle_green_10dp.xml
copy to packages/overlays/NoCutoutOverlay/res/values-it/strings.xml
index 571ec62..07444aa 100644
--- a/packages/SystemUI/res/drawable/circle_green_10dp.xml
+++ b/packages/overlays/NoCutoutOverlay/res/values-it/strings.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
+<?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.
@@ -13,10 +13,9 @@
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size android:height="10dp"
- android:width="10dp" />
- <solid android:color="#34A853" />
-</shape>
\ No newline at end of file
+ -->
+
+<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="9031691255599853162">"Nascondi"</string>
+</resources>
diff --git a/packages/SystemUI/res/drawable/circle_green_10dp.xml b/packages/overlays/NoCutoutOverlay/res/values-ja/strings.xml
similarity index 61%
copy from packages/SystemUI/res/drawable/circle_green_10dp.xml
copy to packages/overlays/NoCutoutOverlay/res/values-ja/strings.xml
index 571ec62..3bf17fb 100644
--- a/packages/SystemUI/res/drawable/circle_green_10dp.xml
+++ b/packages/overlays/NoCutoutOverlay/res/values-ja/strings.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
+<?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.
@@ -13,10 +13,9 @@
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size android:height="10dp"
- android:width="10dp" />
- <solid android:color="#34A853" />
-</shape>
\ No newline at end of file
+ -->
+
+<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="9031691255599853162">"非表示"</string>
+</resources>
diff --git a/packages/SystemUI/res/drawable/circle_green_10dp.xml b/packages/overlays/NoCutoutOverlay/res/values-ka/strings.xml
similarity index 60%
copy from packages/SystemUI/res/drawable/circle_green_10dp.xml
copy to packages/overlays/NoCutoutOverlay/res/values-ka/strings.xml
index 571ec62..1600528 100644
--- a/packages/SystemUI/res/drawable/circle_green_10dp.xml
+++ b/packages/overlays/NoCutoutOverlay/res/values-ka/strings.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
+<?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.
@@ -13,10 +13,9 @@
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size android:height="10dp"
- android:width="10dp" />
- <solid android:color="#34A853" />
-</shape>
\ No newline at end of file
+ -->
+
+<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="9031691255599853162">"დამალვა"</string>
+</resources>
diff --git a/packages/SystemUI/res/drawable/circle_green_10dp.xml b/packages/overlays/NoCutoutOverlay/res/values-km/strings.xml
similarity index 61%
copy from packages/SystemUI/res/drawable/circle_green_10dp.xml
copy to packages/overlays/NoCutoutOverlay/res/values-km/strings.xml
index 571ec62..624b81f 100644
--- a/packages/SystemUI/res/drawable/circle_green_10dp.xml
+++ b/packages/overlays/NoCutoutOverlay/res/values-km/strings.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
+<?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.
@@ -13,10 +13,9 @@
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size android:height="10dp"
- android:width="10dp" />
- <solid android:color="#34A853" />
-</shape>
\ No newline at end of file
+ -->
+
+<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="9031691255599853162">"លាក់"</string>
+</resources>
diff --git a/packages/SystemUI/res/drawable/circle_green_10dp.xml b/packages/overlays/NoCutoutOverlay/res/values-ko/strings.xml
similarity index 61%
copy from packages/SystemUI/res/drawable/circle_green_10dp.xml
copy to packages/overlays/NoCutoutOverlay/res/values-ko/strings.xml
index 571ec62..efb6568 100644
--- a/packages/SystemUI/res/drawable/circle_green_10dp.xml
+++ b/packages/overlays/NoCutoutOverlay/res/values-ko/strings.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
+<?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.
@@ -13,10 +13,9 @@
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size android:height="10dp"
- android:width="10dp" />
- <solid android:color="#34A853" />
-</shape>
\ No newline at end of file
+ -->
+
+<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="9031691255599853162">"숨기기"</string>
+</resources>
diff --git a/packages/SystemUI/res/drawable/circle_green_10dp.xml b/packages/overlays/NoCutoutOverlay/res/values-lo/strings.xml
similarity index 60%
copy from packages/SystemUI/res/drawable/circle_green_10dp.xml
copy to packages/overlays/NoCutoutOverlay/res/values-lo/strings.xml
index 571ec62..8850dfb 100644
--- a/packages/SystemUI/res/drawable/circle_green_10dp.xml
+++ b/packages/overlays/NoCutoutOverlay/res/values-lo/strings.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
+<?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.
@@ -13,10 +13,9 @@
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size android:height="10dp"
- android:width="10dp" />
- <solid android:color="#34A853" />
-</shape>
\ No newline at end of file
+ -->
+
+<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="9031691255599853162">"ເຊື່ອງ"</string>
+</resources>
diff --git a/packages/SystemUI/res/drawable/circle_green_10dp.xml b/packages/overlays/NoCutoutOverlay/res/values-mk/strings.xml
similarity index 61%
copy from packages/SystemUI/res/drawable/circle_green_10dp.xml
copy to packages/overlays/NoCutoutOverlay/res/values-mk/strings.xml
index 571ec62..505c205 100644
--- a/packages/SystemUI/res/drawable/circle_green_10dp.xml
+++ b/packages/overlays/NoCutoutOverlay/res/values-mk/strings.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
+<?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.
@@ -13,10 +13,9 @@
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size android:height="10dp"
- android:width="10dp" />
- <solid android:color="#34A853" />
-</shape>
\ No newline at end of file
+ -->
+
+<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="9031691255599853162">"Сокриј"</string>
+</resources>
diff --git a/packages/SystemUI/res/drawable/circle_green_10dp.xml b/packages/overlays/NoCutoutOverlay/res/values-mn/strings.xml
similarity index 61%
copy from packages/SystemUI/res/drawable/circle_green_10dp.xml
copy to packages/overlays/NoCutoutOverlay/res/values-mn/strings.xml
index 571ec62..7e2719b 100644
--- a/packages/SystemUI/res/drawable/circle_green_10dp.xml
+++ b/packages/overlays/NoCutoutOverlay/res/values-mn/strings.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
+<?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.
@@ -13,10 +13,9 @@
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size android:height="10dp"
- android:width="10dp" />
- <solid android:color="#34A853" />
-</shape>
\ No newline at end of file
+ -->
+
+<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="9031691255599853162">"Нуух"</string>
+</resources>
diff --git a/packages/SystemUI/res/drawable/circle_green_10dp.xml b/packages/overlays/NoCutoutOverlay/res/values-ms/strings.xml
similarity index 61%
copy from packages/SystemUI/res/drawable/circle_green_10dp.xml
copy to packages/overlays/NoCutoutOverlay/res/values-ms/strings.xml
index 571ec62..6c017b3 100644
--- a/packages/SystemUI/res/drawable/circle_green_10dp.xml
+++ b/packages/overlays/NoCutoutOverlay/res/values-ms/strings.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
+<?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.
@@ -13,10 +13,9 @@
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size android:height="10dp"
- android:width="10dp" />
- <solid android:color="#34A853" />
-</shape>
\ No newline at end of file
+ -->
+
+<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="9031691255599853162">"Sembunyikan"</string>
+</resources>
diff --git a/packages/SystemUI/res/drawable/circle_green_10dp.xml b/packages/overlays/NoCutoutOverlay/res/values-nl/strings.xml
similarity index 61%
copy from packages/SystemUI/res/drawable/circle_green_10dp.xml
copy to packages/overlays/NoCutoutOverlay/res/values-nl/strings.xml
index 571ec62..00900f8 100644
--- a/packages/SystemUI/res/drawable/circle_green_10dp.xml
+++ b/packages/overlays/NoCutoutOverlay/res/values-nl/strings.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
+<?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.
@@ -13,10 +13,9 @@
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size android:height="10dp"
- android:width="10dp" />
- <solid android:color="#34A853" />
-</shape>
\ No newline at end of file
+ -->
+
+<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="9031691255599853162">"Verbergen"</string>
+</resources>
diff --git a/packages/SystemUI/res/drawable/circle_green_10dp.xml b/packages/overlays/NoCutoutOverlay/res/values-pa/strings.xml
similarity index 61%
copy from packages/SystemUI/res/drawable/circle_green_10dp.xml
copy to packages/overlays/NoCutoutOverlay/res/values-pa/strings.xml
index 571ec62..9f37e0b 100644
--- a/packages/SystemUI/res/drawable/circle_green_10dp.xml
+++ b/packages/overlays/NoCutoutOverlay/res/values-pa/strings.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
+<?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.
@@ -13,10 +13,9 @@
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size android:height="10dp"
- android:width="10dp" />
- <solid android:color="#34A853" />
-</shape>
\ No newline at end of file
+ -->
+
+<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="9031691255599853162">"ਲੁਕਾਓ"</string>
+</resources>
diff --git a/packages/SystemUI/res/drawable/circle_green_10dp.xml b/packages/overlays/NoCutoutOverlay/res/values-pt-rBR/strings.xml
similarity index 61%
copy from packages/SystemUI/res/drawable/circle_green_10dp.xml
copy to packages/overlays/NoCutoutOverlay/res/values-pt-rBR/strings.xml
index 571ec62..351c1cd 100644
--- a/packages/SystemUI/res/drawable/circle_green_10dp.xml
+++ b/packages/overlays/NoCutoutOverlay/res/values-pt-rBR/strings.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
+<?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.
@@ -13,10 +13,9 @@
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size android:height="10dp"
- android:width="10dp" />
- <solid android:color="#34A853" />
-</shape>
\ No newline at end of file
+ -->
+
+<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="9031691255599853162">"Ocultar"</string>
+</resources>
diff --git a/packages/SystemUI/res/drawable/circle_green_10dp.xml b/packages/overlays/NoCutoutOverlay/res/values-pt-rPT/strings.xml
similarity index 61%
copy from packages/SystemUI/res/drawable/circle_green_10dp.xml
copy to packages/overlays/NoCutoutOverlay/res/values-pt-rPT/strings.xml
index 571ec62..351c1cd 100644
--- a/packages/SystemUI/res/drawable/circle_green_10dp.xml
+++ b/packages/overlays/NoCutoutOverlay/res/values-pt-rPT/strings.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
+<?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.
@@ -13,10 +13,9 @@
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size android:height="10dp"
- android:width="10dp" />
- <solid android:color="#34A853" />
-</shape>
\ No newline at end of file
+ -->
+
+<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="9031691255599853162">"Ocultar"</string>
+</resources>
diff --git a/packages/SystemUI/res/drawable/circle_green_10dp.xml b/packages/overlays/NoCutoutOverlay/res/values-pt/strings.xml
similarity index 61%
copy from packages/SystemUI/res/drawable/circle_green_10dp.xml
copy to packages/overlays/NoCutoutOverlay/res/values-pt/strings.xml
index 571ec62..351c1cd 100644
--- a/packages/SystemUI/res/drawable/circle_green_10dp.xml
+++ b/packages/overlays/NoCutoutOverlay/res/values-pt/strings.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
+<?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.
@@ -13,10 +13,9 @@
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size android:height="10dp"
- android:width="10dp" />
- <solid android:color="#34A853" />
-</shape>
\ No newline at end of file
+ -->
+
+<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="9031691255599853162">"Ocultar"</string>
+</resources>
diff --git a/packages/SystemUI/res/drawable/circle_green_10dp.xml b/packages/overlays/NoCutoutOverlay/res/values-ro/strings.xml
similarity index 61%
copy from packages/SystemUI/res/drawable/circle_green_10dp.xml
copy to packages/overlays/NoCutoutOverlay/res/values-ro/strings.xml
index 571ec62..e6281fd 100644
--- a/packages/SystemUI/res/drawable/circle_green_10dp.xml
+++ b/packages/overlays/NoCutoutOverlay/res/values-ro/strings.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
+<?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.
@@ -13,10 +13,9 @@
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size android:height="10dp"
- android:width="10dp" />
- <solid android:color="#34A853" />
-</shape>
\ No newline at end of file
+ -->
+
+<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="9031691255599853162">"Ascundeți"</string>
+</resources>
diff --git a/packages/SystemUI/res/drawable/circle_green_10dp.xml b/packages/overlays/NoCutoutOverlay/res/values-ru/strings.xml
similarity index 61%
copy from packages/SystemUI/res/drawable/circle_green_10dp.xml
copy to packages/overlays/NoCutoutOverlay/res/values-ru/strings.xml
index 571ec62..9018396 100644
--- a/packages/SystemUI/res/drawable/circle_green_10dp.xml
+++ b/packages/overlays/NoCutoutOverlay/res/values-ru/strings.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
+<?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.
@@ -13,10 +13,9 @@
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size android:height="10dp"
- android:width="10dp" />
- <solid android:color="#34A853" />
-</shape>
\ No newline at end of file
+ -->
+
+<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="9031691255599853162">"Скрыть"</string>
+</resources>
diff --git a/packages/SystemUI/res/drawable/circle_green_10dp.xml b/packages/overlays/NoCutoutOverlay/res/values-si/strings.xml
similarity index 60%
copy from packages/SystemUI/res/drawable/circle_green_10dp.xml
copy to packages/overlays/NoCutoutOverlay/res/values-si/strings.xml
index 571ec62..b06a52c 100644
--- a/packages/SystemUI/res/drawable/circle_green_10dp.xml
+++ b/packages/overlays/NoCutoutOverlay/res/values-si/strings.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
+<?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.
@@ -13,10 +13,9 @@
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size android:height="10dp"
- android:width="10dp" />
- <solid android:color="#34A853" />
-</shape>
\ No newline at end of file
+ -->
+
+<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="9031691255599853162">"සඟවන්න"</string>
+</resources>
diff --git a/packages/SystemUI/res/drawable/circle_green_10dp.xml b/packages/overlays/NoCutoutOverlay/res/values-sk/strings.xml
similarity index 61%
copy from packages/SystemUI/res/drawable/circle_green_10dp.xml
copy to packages/overlays/NoCutoutOverlay/res/values-sk/strings.xml
index 571ec62..965d95b 100644
--- a/packages/SystemUI/res/drawable/circle_green_10dp.xml
+++ b/packages/overlays/NoCutoutOverlay/res/values-sk/strings.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
+<?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.
@@ -13,10 +13,9 @@
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size android:height="10dp"
- android:width="10dp" />
- <solid android:color="#34A853" />
-</shape>
\ No newline at end of file
+ -->
+
+<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="9031691255599853162">"Skryť"</string>
+</resources>
diff --git a/packages/SystemUI/res/drawable/circle_green_10dp.xml b/packages/overlays/NoCutoutOverlay/res/values-sr/strings.xml
similarity index 61%
copy from packages/SystemUI/res/drawable/circle_green_10dp.xml
copy to packages/overlays/NoCutoutOverlay/res/values-sr/strings.xml
index 571ec62..26afbf9 100644
--- a/packages/SystemUI/res/drawable/circle_green_10dp.xml
+++ b/packages/overlays/NoCutoutOverlay/res/values-sr/strings.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
+<?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.
@@ -13,10 +13,9 @@
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size android:height="10dp"
- android:width="10dp" />
- <solid android:color="#34A853" />
-</shape>
\ No newline at end of file
+ -->
+
+<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="9031691255599853162">"Сакриј"</string>
+</resources>
diff --git a/packages/SystemUI/res/drawable/circle_green_10dp.xml b/packages/overlays/NoCutoutOverlay/res/values-sw/strings.xml
similarity index 61%
copy from packages/SystemUI/res/drawable/circle_green_10dp.xml
copy to packages/overlays/NoCutoutOverlay/res/values-sw/strings.xml
index 571ec62..58e35e2 100644
--- a/packages/SystemUI/res/drawable/circle_green_10dp.xml
+++ b/packages/overlays/NoCutoutOverlay/res/values-sw/strings.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
+<?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.
@@ -13,10 +13,9 @@
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size android:height="10dp"
- android:width="10dp" />
- <solid android:color="#34A853" />
-</shape>
\ No newline at end of file
+ -->
+
+<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="9031691255599853162">"Ficha"</string>
+</resources>
diff --git a/packages/SystemUI/res/drawable/circle_green_10dp.xml b/packages/overlays/NoCutoutOverlay/res/values-th/strings.xml
similarity index 61%
copy from packages/SystemUI/res/drawable/circle_green_10dp.xml
copy to packages/overlays/NoCutoutOverlay/res/values-th/strings.xml
index 571ec62..1c8bd9d 100644
--- a/packages/SystemUI/res/drawable/circle_green_10dp.xml
+++ b/packages/overlays/NoCutoutOverlay/res/values-th/strings.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
+<?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.
@@ -13,10 +13,9 @@
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size android:height="10dp"
- android:width="10dp" />
- <solid android:color="#34A853" />
-</shape>
\ No newline at end of file
+ -->
+
+<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="9031691255599853162">"ซ่อน"</string>
+</resources>
diff --git a/packages/SystemUI/res/drawable/circle_green_10dp.xml b/packages/overlays/NoCutoutOverlay/res/values-tl/strings.xml
similarity index 61%
copy from packages/SystemUI/res/drawable/circle_green_10dp.xml
copy to packages/overlays/NoCutoutOverlay/res/values-tl/strings.xml
index 571ec62..cc45f63 100644
--- a/packages/SystemUI/res/drawable/circle_green_10dp.xml
+++ b/packages/overlays/NoCutoutOverlay/res/values-tl/strings.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
+<?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.
@@ -13,10 +13,9 @@
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size android:height="10dp"
- android:width="10dp" />
- <solid android:color="#34A853" />
-</shape>
\ No newline at end of file
+ -->
+
+<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="9031691255599853162">"Itago"</string>
+</resources>
diff --git a/packages/SystemUI/res/drawable/circle_green_10dp.xml b/packages/overlays/NoCutoutOverlay/res/values-tr/strings.xml
similarity index 61%
copy from packages/SystemUI/res/drawable/circle_green_10dp.xml
copy to packages/overlays/NoCutoutOverlay/res/values-tr/strings.xml
index 571ec62..b20f1f7 100644
--- a/packages/SystemUI/res/drawable/circle_green_10dp.xml
+++ b/packages/overlays/NoCutoutOverlay/res/values-tr/strings.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
+<?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.
@@ -13,10 +13,9 @@
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size android:height="10dp"
- android:width="10dp" />
- <solid android:color="#34A853" />
-</shape>
\ No newline at end of file
+ -->
+
+<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="9031691255599853162">"Gizle"</string>
+</resources>
diff --git a/packages/SystemUI/res/drawable/circle_green_10dp.xml b/packages/overlays/NoCutoutOverlay/res/values-uk/strings.xml
similarity index 61%
copy from packages/SystemUI/res/drawable/circle_green_10dp.xml
copy to packages/overlays/NoCutoutOverlay/res/values-uk/strings.xml
index 571ec62..938b0e2 100644
--- a/packages/SystemUI/res/drawable/circle_green_10dp.xml
+++ b/packages/overlays/NoCutoutOverlay/res/values-uk/strings.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
+<?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.
@@ -13,10 +13,9 @@
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size android:height="10dp"
- android:width="10dp" />
- <solid android:color="#34A853" />
-</shape>
\ No newline at end of file
+ -->
+
+<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="9031691255599853162">"Сховати"</string>
+</resources>
diff --git a/packages/SystemUI/res/drawable/circle_green_10dp.xml b/packages/overlays/NoCutoutOverlay/res/values-uz/strings.xml
similarity index 61%
copy from packages/SystemUI/res/drawable/circle_green_10dp.xml
copy to packages/overlays/NoCutoutOverlay/res/values-uz/strings.xml
index 571ec62..5d22045 100644
--- a/packages/SystemUI/res/drawable/circle_green_10dp.xml
+++ b/packages/overlays/NoCutoutOverlay/res/values-uz/strings.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
+<?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.
@@ -13,10 +13,9 @@
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size android:height="10dp"
- android:width="10dp" />
- <solid android:color="#34A853" />
-</shape>
\ No newline at end of file
+ -->
+
+<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="9031691255599853162">"Berkitish"</string>
+</resources>
diff --git a/packages/SystemUI/res/drawable/circle_green_10dp.xml b/packages/overlays/NoCutoutOverlay/res/values-zh-rHK/strings.xml
similarity index 61%
copy from packages/SystemUI/res/drawable/circle_green_10dp.xml
copy to packages/overlays/NoCutoutOverlay/res/values-zh-rHK/strings.xml
index 571ec62..abb8e81 100644
--- a/packages/SystemUI/res/drawable/circle_green_10dp.xml
+++ b/packages/overlays/NoCutoutOverlay/res/values-zh-rHK/strings.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
+<?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.
@@ -13,10 +13,9 @@
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size android:height="10dp"
- android:width="10dp" />
- <solid android:color="#34A853" />
-</shape>
\ No newline at end of file
+ -->
+
+<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="9031691255599853162">"隱藏"</string>
+</resources>
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 3bb6e08..13340ba 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -554,7 +554,7 @@
}
if (onClickIntent != null) {
- views.setOnClickPendingIntent(R.id.work_widget_mask_frame,
+ views.setOnClickPendingIntent(android.R.id.background,
PendingIntent.getActivity(mContext, 0, onClickIntent,
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE));
}
@@ -1839,8 +1839,6 @@
// For a full update we replace the RemoteViews completely.
widget.views = views;
}
- widget.views.setProviderInstanceId(UPDATE_COUNTER.get());
-
int memoryUsage;
if ((UserHandle.getAppId(Binder.getCallingUid()) != Process.SYSTEM_UID) &&
(widget.views != null) &&
@@ -1942,13 +1940,14 @@
return;
}
if (updateViews != null) {
+ updateViews = new RemoteViews(updateViews);
updateViews.setProviderInstanceId(requestId);
}
SomeArgs args = SomeArgs.obtain();
args.arg1 = widget.host;
args.arg2 = widget.host.callbacks;
- args.arg3 = (updateViews != null) ? updateViews.clone() : null;
+ args.arg3 = updateViews;
args.arg4 = requestId;
args.argi1 = widget.appWidgetId;
diff --git a/services/autofill/java/com/android/server/autofill/ClientSuggestionsSession.java b/services/autofill/java/com/android/server/autofill/ClientSuggestionsSession.java
deleted file mode 100644
index 715697d..0000000
--- a/services/autofill/java/com/android/server/autofill/ClientSuggestionsSession.java
+++ /dev/null
@@ -1,293 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.autofill;
-
-import static android.service.autofill.FillRequest.INVALID_REQUEST_ID;
-
-import static com.android.server.autofill.Helper.sVerbose;
-
-import android.annotation.Nullable;
-import android.annotation.UserIdInt;
-import android.app.AppGlobals;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.graphics.drawable.Drawable;
-import android.os.Handler;
-import android.os.ICancellationSignal;
-import android.os.RemoteException;
-import android.service.autofill.Dataset;
-import android.service.autofill.FillResponse;
-import android.service.autofill.IFillCallback;
-import android.service.autofill.SaveInfo;
-import android.text.TextUtils;
-import android.text.format.DateUtils;
-import android.util.Slog;
-import android.view.autofill.AutofillId;
-import android.view.autofill.IAutoFillManagerClient;
-import android.view.inputmethod.InlineSuggestionsRequest;
-
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.infra.AndroidFuture;
-
-import java.util.List;
-import java.util.concurrent.CancellationException;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-import java.util.concurrent.atomic.AtomicReference;
-
-/**
- * Maintains a client suggestions session with the
- * {@link android.view.autofill.AutofillRequestCallback} through the {@link IAutoFillManagerClient}.
- *
- */
-final class ClientSuggestionsSession {
-
- private static final String TAG = "ClientSuggestionsSession";
- private static final long TIMEOUT_REMOTE_REQUEST_MILLIS = 15 * DateUtils.SECOND_IN_MILLIS;
-
- private final int mSessionId;
- private final IAutoFillManagerClient mClient;
- private final Handler mHandler;
- private final ComponentName mComponentName;
-
- private final RemoteFillService.FillServiceCallbacks mCallbacks;
-
- private final Object mLock = new Object();
- @GuardedBy("mLock")
- private AndroidFuture<FillResponse> mPendingFillRequest;
- @GuardedBy("mLock")
- private int mPendingFillRequestId = INVALID_REQUEST_ID;
-
- ClientSuggestionsSession(int sessionId, IAutoFillManagerClient client, Handler handler,
- ComponentName componentName, RemoteFillService.FillServiceCallbacks callbacks) {
- mSessionId = sessionId;
- mClient = client;
- mHandler = handler;
- mComponentName = componentName;
- mCallbacks = callbacks;
- }
-
- void onFillRequest(int requestId, InlineSuggestionsRequest inlineRequest, int flags) {
- final AtomicReference<ICancellationSignal> cancellationSink = new AtomicReference<>();
- final AtomicReference<AndroidFuture<FillResponse>> futureRef = new AtomicReference<>();
- final AndroidFuture<FillResponse> fillRequest = new AndroidFuture<>();
-
- mHandler.post(() -> {
- if (sVerbose) {
- Slog.v(TAG, "calling onFillRequest() for id=" + requestId);
- }
-
- try {
- mClient.requestFillFromClient(requestId, inlineRequest,
- new FillCallbackImpl(fillRequest, futureRef, cancellationSink));
- } catch (RemoteException e) {
- fillRequest.completeExceptionally(e);
- }
- });
-
- fillRequest.orTimeout(TIMEOUT_REMOTE_REQUEST_MILLIS, TimeUnit.MILLISECONDS);
- futureRef.set(fillRequest);
-
- synchronized (mLock) {
- mPendingFillRequest = fillRequest;
- mPendingFillRequestId = requestId;
- }
-
- fillRequest.whenComplete((res, err) -> mHandler.post(() -> {
- synchronized (mLock) {
- mPendingFillRequest = null;
- mPendingFillRequestId = INVALID_REQUEST_ID;
- }
- if (err == null) {
- processAutofillId(res);
- mCallbacks.onFillRequestSuccess(requestId, res,
- mComponentName.getPackageName(), flags);
- } else {
- Slog.e(TAG, "Error calling on client fill request", err);
- if (err instanceof TimeoutException) {
- dispatchCancellationSignal(cancellationSink.get());
- mCallbacks.onFillRequestTimeout(requestId);
- } else if (err instanceof CancellationException) {
- dispatchCancellationSignal(cancellationSink.get());
- } else {
- mCallbacks.onFillRequestFailure(requestId, err.getMessage());
- }
- }
- }));
- }
-
- /**
- * Gets the application info for the component.
- */
- @Nullable
- static ApplicationInfo getAppInfo(ComponentName comp, @UserIdInt int userId) {
- try {
- ApplicationInfo si = AppGlobals.getPackageManager().getApplicationInfo(
- comp.getPackageName(),
- PackageManager.GET_META_DATA,
- userId);
- if (si != null) {
- return si;
- }
- } catch (RemoteException e) {
- }
- return null;
- }
-
- /**
- * Gets the user-visible name of the application.
- */
- @Nullable
- @GuardedBy("mLock")
- static CharSequence getAppLabelLocked(Context context, ApplicationInfo appInfo) {
- return appInfo == null ? null : appInfo.loadSafeLabel(
- context.getPackageManager(), 0 /* do not ellipsize */,
- TextUtils.SAFE_STRING_FLAG_FIRST_LINE | TextUtils.SAFE_STRING_FLAG_TRIM);
- }
-
- /**
- * Gets the user-visible icon of the application.
- */
- @Nullable
- @GuardedBy("mLock")
- static Drawable getAppIconLocked(Context context, ApplicationInfo appInfo) {
- return appInfo == null ? null : appInfo.loadIcon(context.getPackageManager());
- }
-
- int cancelCurrentRequest() {
- synchronized (mLock) {
- return mPendingFillRequest != null && mPendingFillRequest.cancel(false)
- ? mPendingFillRequestId
- : INVALID_REQUEST_ID;
- }
- }
-
- /**
- * The {@link AutofillId} which the client gets from its view is not contain the session id,
- * but Autofill framework is using the {@link AutofillId} with a session id. So before using
- * those ids in the Autofill framework, applies the current session id.
- *
- * @param res which response need to apply for a session id
- */
- private void processAutofillId(FillResponse res) {
- if (res == null) {
- return;
- }
-
- final List<Dataset> datasets = res.getDatasets();
- if (datasets != null && !datasets.isEmpty()) {
- for (int i = 0; i < datasets.size(); i++) {
- final Dataset dataset = datasets.get(i);
- if (dataset != null) {
- applySessionId(dataset.getFieldIds());
- }
- }
- }
-
- final SaveInfo saveInfo = res.getSaveInfo();
- if (saveInfo != null) {
- applySessionId(saveInfo.getOptionalIds());
- applySessionId(saveInfo.getRequiredIds());
- applySessionId(saveInfo.getSanitizerValues());
- applySessionId(saveInfo.getTriggerId());
- }
- }
-
- private void applySessionId(List<AutofillId> ids) {
- if (ids == null || ids.isEmpty()) {
- return;
- }
-
- for (int i = 0; i < ids.size(); i++) {
- applySessionId(ids.get(i));
- }
- }
-
- private void applySessionId(AutofillId[][] ids) {
- if (ids == null) {
- return;
- }
- for (int i = 0; i < ids.length; i++) {
- applySessionId(ids[i]);
- }
- }
-
- private void applySessionId(AutofillId[] ids) {
- if (ids == null) {
- return;
- }
- for (int i = 0; i < ids.length; i++) {
- applySessionId(ids[i]);
- }
- }
-
- private void applySessionId(AutofillId id) {
- if (id == null) {
- return;
- }
- id.setSessionId(mSessionId);
- }
-
- private void dispatchCancellationSignal(@Nullable ICancellationSignal signal) {
- if (signal == null) {
- return;
- }
- try {
- signal.cancel();
- } catch (RemoteException e) {
- Slog.e(TAG, "Error requesting a cancellation", e);
- }
- }
-
- private class FillCallbackImpl extends IFillCallback.Stub {
- final AndroidFuture<FillResponse> mFillRequest;
- final AtomicReference<AndroidFuture<FillResponse>> mFutureRef;
- final AtomicReference<ICancellationSignal> mCancellationSink;
-
- FillCallbackImpl(AndroidFuture<FillResponse> fillRequest,
- AtomicReference<AndroidFuture<FillResponse>> futureRef,
- AtomicReference<ICancellationSignal> cancellationSink) {
- mFillRequest = fillRequest;
- mFutureRef = futureRef;
- mCancellationSink = cancellationSink;
- }
-
- @Override
- public void onCancellable(ICancellationSignal cancellation) {
- AndroidFuture<FillResponse> future = mFutureRef.get();
- if (future != null && future.isCancelled()) {
- dispatchCancellationSignal(cancellation);
- } else {
- mCancellationSink.set(cancellation);
- }
- }
-
- @Override
- public void onSuccess(FillResponse response) {
- mFillRequest.complete(response);
- }
-
- @Override
- public void onFailure(int requestId, CharSequence message) {
- String errorMessage = message == null ? "" : String.valueOf(message);
- mFillRequest.completeExceptionally(
- new RuntimeException(errorMessage));
- }
- }
-}
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 042631d..320047f 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -26,7 +26,6 @@
import static android.view.autofill.AutofillManager.ACTION_VALUE_CHANGED;
import static android.view.autofill.AutofillManager.ACTION_VIEW_ENTERED;
import static android.view.autofill.AutofillManager.ACTION_VIEW_EXITED;
-import static android.view.autofill.AutofillManager.FLAG_ENABLED_CLIENT_SUGGESTIONS;
import static android.view.autofill.AutofillManager.FLAG_SMART_SUGGESTION_SYSTEM;
import static android.view.autofill.AutofillManager.getSmartSuggestionModeToString;
@@ -54,7 +53,6 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
-import android.content.pm.ApplicationInfo;
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
@@ -348,9 +346,6 @@
*/
private final AssistDataReceiverImpl mAssistReceiver = new AssistDataReceiverImpl();
- @Nullable
- private ClientSuggestionsSession mClientSuggestionsSession;
-
void onSwitchInputMethodLocked() {
// One caveat is that for the case where the focus is on a field for which regular autofill
// returns null, and augmented autofill is triggered, and then the user switches the input
@@ -421,10 +416,6 @@
/** Whether the current {@link FillResponse} is expired. */
@GuardedBy("mLock")
private boolean mExpiredResponse;
-
- /** Whether the client is using {@link android.view.autofill.AutofillRequestCallback}. */
- @GuardedBy("mLock")
- private boolean mClientSuggestionsEnabled;
}
/**
@@ -450,19 +441,13 @@
return;
}
mPendingInlineSuggestionsRequest = inlineSuggestionsRequest;
- maybeRequestFillFromServiceLocked();
+ maybeRequestFillLocked();
viewState.resetState(ViewState.STATE_PENDING_CREATE_INLINE_REQUEST);
}
} : null;
}
- void newAutofillRequestLocked(@Nullable InlineSuggestionsRequest inlineRequest) {
- mPendingFillRequest = null;
- mWaitForInlineRequest = inlineRequest != null;
- mPendingInlineSuggestionsRequest = inlineRequest;
- }
-
- void maybeRequestFillFromServiceLocked() {
+ void maybeRequestFillLocked() {
if (mPendingFillRequest == null) {
return;
}
@@ -472,12 +457,9 @@
return;
}
- if (mPendingInlineSuggestionsRequest.isServiceSupported()) {
- mPendingFillRequest = new FillRequest(mPendingFillRequest.getId(),
- mPendingFillRequest.getFillContexts(),
- mPendingFillRequest.getClientState(),
- mPendingFillRequest.getFlags(), mPendingInlineSuggestionsRequest);
- }
+ mPendingFillRequest = new FillRequest(mPendingFillRequest.getId(),
+ mPendingFillRequest.getFillContexts(), mPendingFillRequest.getClientState(),
+ mPendingFillRequest.getFlags(), mPendingInlineSuggestionsRequest);
}
mRemoteFillService.onFillRequest(mPendingFillRequest);
@@ -584,7 +566,7 @@
/*inlineSuggestionsRequest=*/null);
mPendingFillRequest = request;
- maybeRequestFillFromServiceLocked();
+ maybeRequestFillLocked();
}
if (mActivityToken != null) {
@@ -746,39 +728,30 @@
}
/**
- * Cancels the last request sent to the {@link #mRemoteFillService} or the
- * {@link #mClientSuggestionsSession}.
+ * Cancels the last request sent to the {@link #mRemoteFillService}.
*/
@GuardedBy("mLock")
private void cancelCurrentRequestLocked() {
- if (mRemoteFillService == null && mClientSuggestionsSession == null) {
- wtf(null, "cancelCurrentRequestLocked() called without a remote service or a "
- + "client suggestions session. mForAugmentedAutofillOnly: %s",
- mSessionFlags.mAugmentedAutofillOnly);
+ if (mRemoteFillService == null) {
+ wtf(null, "cancelCurrentRequestLocked() called without a remote service. "
+ + "mForAugmentedAutofillOnly: %s", mSessionFlags.mAugmentedAutofillOnly);
return;
}
+ final int canceledRequest = mRemoteFillService.cancelCurrentRequest();
- if (mRemoteFillService != null) {
- final int canceledRequest = mRemoteFillService.cancelCurrentRequest();
+ // Remove the FillContext as there will never be a response for the service
+ if (canceledRequest != INVALID_REQUEST_ID && mContexts != null) {
+ final int numContexts = mContexts.size();
- // Remove the FillContext as there will never be a response for the service
- if (canceledRequest != INVALID_REQUEST_ID && mContexts != null) {
- final int numContexts = mContexts.size();
-
- // It is most likely the last context, hence search backwards
- for (int i = numContexts - 1; i >= 0; i--) {
- if (mContexts.get(i).getRequestId() == canceledRequest) {
- if (sDebug) Slog.d(TAG, "cancelCurrentRequest(): id = " + canceledRequest);
- mContexts.remove(i);
- break;
- }
+ // It is most likely the last context, hence search backwards
+ for (int i = numContexts - 1; i >= 0; i--) {
+ if (mContexts.get(i).getRequestId() == canceledRequest) {
+ if (sDebug) Slog.d(TAG, "cancelCurrentRequest(): id = " + canceledRequest);
+ mContexts.remove(i);
+ break;
}
}
}
-
- if (mClientSuggestionsSession != null) {
- mClientSuggestionsSession.cancelCurrentRequest();
- }
}
private boolean isViewFocusedLocked(int flags) {
@@ -843,30 +816,17 @@
// structure is taken. This causes only one fill request per burst of focus changes.
cancelCurrentRequestLocked();
- // Only ask IME to create inline suggestions request when
- // 1. Autofill provider supports it or client enabled client suggestions.
- // 2. The render service is available.
- // 3. The view is focused. (The view may not be focused if the autofill is triggered
- // manually.)
+ // Only ask IME to create inline suggestions request if Autofill provider supports it and
+ // the render service is available except the autofill is triggered manually and the view
+ // is also not focused.
final RemoteInlineSuggestionRenderService remoteRenderService =
mService.getRemoteInlineSuggestionRenderServiceLocked();
- if ((mSessionFlags.mInlineSupportedByService || mSessionFlags.mClientSuggestionsEnabled)
+ if (mSessionFlags.mInlineSupportedByService
&& remoteRenderService != null
&& isViewFocusedLocked(flags)) {
- Consumer<InlineSuggestionsRequest> inlineSuggestionsRequestConsumer;
- if (mSessionFlags.mClientSuggestionsEnabled) {
- final int finalRequestId = requestId;
- inlineSuggestionsRequestConsumer = (inlineSuggestionsRequest) -> {
- // Using client suggestions
- synchronized (mLock) {
- onClientFillRequestLocked(finalRequestId, inlineSuggestionsRequest);
- }
- viewState.resetState(ViewState.STATE_PENDING_CREATE_INLINE_REQUEST);
- };
- } else {
- inlineSuggestionsRequestConsumer = mAssistReceiver.newAutofillRequestLocked(
- viewState, /* isInlineRequest= */ true);
- }
+ Consumer<InlineSuggestionsRequest> inlineSuggestionsRequestConsumer =
+ mAssistReceiver.newAutofillRequestLocked(viewState,
+ /* isInlineRequest= */ true);
if (inlineSuggestionsRequestConsumer != null) {
final AutofillId focusedId = mCurrentViewId;
final int requestIdCopy = requestId;
@@ -882,24 +842,11 @@
);
viewState.setState(ViewState.STATE_PENDING_CREATE_INLINE_REQUEST);
}
- } else if (mSessionFlags.mClientSuggestionsEnabled) {
- // Request client suggestions for the dropdown mode
- onClientFillRequestLocked(requestId, null);
} else {
mAssistReceiver.newAutofillRequestLocked(viewState, /* isInlineRequest= */ false);
}
- if (mSessionFlags.mClientSuggestionsEnabled) {
- // Using client suggestions, unnecessary request AssistStructure
- return;
- }
-
// Now request the assist structure data.
- requestAssistStructureLocked(requestId, flags);
- }
-
- @GuardedBy("mLock")
- private void requestAssistStructureLocked(int requestId, int flags) {
try {
final Bundle receiverExtras = new Bundle();
receiverExtras.putInt(EXTRA_REQUEST_ID, requestId);
@@ -948,13 +895,10 @@
mComponentName = componentName;
mCompatMode = compatMode;
mSessionState = STATE_ACTIVE;
-
synchronized (mLock) {
mSessionFlags = new SessionFlags();
mSessionFlags.mAugmentedAutofillOnly = forAugmentedAutofillOnly;
mSessionFlags.mInlineSupportedByService = mService.isInlineSuggestionsEnabledLocked();
- mSessionFlags.mClientSuggestionsEnabled =
- (mFlags & FLAG_ENABLED_CLIENT_SUGGESTIONS) != 0;
setClientLocked(client);
}
@@ -1066,13 +1010,12 @@
if (requestLog != null) {
requestLog.addTaggedData(MetricsEvent.FIELD_AUTOFILL_NUM_DATASETS, -1);
}
- processNullResponseOrFallbackLocked(requestId, requestFlags);
+ processNullResponseLocked(requestId, requestFlags);
return;
}
fieldClassificationIds = response.getFieldClassificationIds();
- if (!mSessionFlags.mClientSuggestionsEnabled && fieldClassificationIds != null
- && !mService.isFieldClassificationEnabledLocked()) {
+ if (fieldClassificationIds != null && !mService.isFieldClassificationEnabledLocked()) {
Slog.w(TAG, "Ignoring " + response + " because field detection is disabled");
processNullResponseLocked(requestId, requestFlags);
return;
@@ -1151,26 +1094,6 @@
}
}
- @GuardedBy("mLock")
- private void processNullResponseOrFallbackLocked(int requestId, int flags) {
- if (!mSessionFlags.mClientSuggestionsEnabled) {
- processNullResponseLocked(requestId, flags);
- return;
- }
-
- // fallback to the default platform password manager
- mSessionFlags.mClientSuggestionsEnabled = false;
-
- final InlineSuggestionsRequest inlineRequest =
- (mLastInlineSuggestionsRequest != null
- && mLastInlineSuggestionsRequest.first == requestId)
- ? mLastInlineSuggestionsRequest.second : null;
- mAssistReceiver.newAutofillRequestLocked(inlineRequest);
- requestAssistStructureLocked(requestId,
- flags & ~FLAG_ENABLED_CLIENT_SUGGESTIONS);
- return;
- }
-
// FillServiceCallbacks
@Override
public void onFillRequestFailure(int requestId, @Nullable CharSequence message) {
@@ -3109,22 +3032,13 @@
filterText = value.getTextValue().toString();
}
- final CharSequence targetLabel;
- final Drawable targetIcon;
+ final CharSequence serviceLabel;
+ final Drawable serviceIcon;
synchronized (mLock) {
- if (mSessionFlags.mClientSuggestionsEnabled) {
- final ApplicationInfo appInfo = ClientSuggestionsSession.getAppInfo(mComponentName,
- mService.getUserId());
- targetLabel = ClientSuggestionsSession.getAppLabelLocked(
- mService.getMaster().getContext(), appInfo);
- targetIcon = ClientSuggestionsSession.getAppIconLocked(
- mService.getMaster().getContext(), appInfo);
- } else {
- targetLabel = mService.getServiceLabelLocked();
- targetIcon = mService.getServiceIconLocked();
- }
+ serviceLabel = mService.getServiceLabelLocked();
+ serviceIcon = mService.getServiceIconLocked();
}
- if (targetLabel == null || targetIcon == null) {
+ if (serviceLabel == null || serviceIcon == null) {
wtf(null, "onFillReady(): no service label or icon");
return;
}
@@ -3144,7 +3058,7 @@
getUiForShowing().showFillUi(filledId, response, filterText,
mService.getServicePackageName(), mComponentName,
- targetLabel, targetIcon, this, id, mCompatMode);
+ serviceLabel, serviceIcon, this, id, mCompatMode);
mService.logDatasetShown(id, mClientState);
@@ -3191,17 +3105,6 @@
return false;
}
- final InlineSuggestionsRequest request = inlineSuggestionsRequest.get();
- if (mSessionFlags.mClientSuggestionsEnabled && !request.isClientSupported()
- || !mSessionFlags.mClientSuggestionsEnabled && !request.isServiceSupported()) {
- if (sDebug) {
- Slog.d(TAG, "Inline suggestions not supported for "
- + (mSessionFlags.mClientSuggestionsEnabled ? "client" : "service")
- + ". Falling back to dropdown.");
- }
- return false;
- }
-
final RemoteInlineSuggestionRenderService remoteRenderService =
mService.getRemoteInlineSuggestionRenderServiceLocked();
if (remoteRenderService == null) {
@@ -3210,7 +3113,7 @@
}
final InlineFillUi.InlineFillUiInfo inlineFillUiInfo =
- new InlineFillUi.InlineFillUiInfo(request, focusedId,
+ new InlineFillUi.InlineFillUiInfo(inlineSuggestionsRequest.get(), focusedId,
filterText, remoteRenderService, userId, id);
InlineFillUi inlineFillUi = InlineFillUi.forAutofill(inlineFillUiInfo, response,
new InlineFillUi.InlineSuggestionUiCallback() {
@@ -3812,25 +3715,6 @@
}
}
- @GuardedBy("mLock")
- private void onClientFillRequestLocked(int requestId,
- InlineSuggestionsRequest inlineSuggestionsRequest) {
- if (mClientSuggestionsSession == null) {
- mClientSuggestionsSession = new ClientSuggestionsSession(id, mClient, mHandler,
- mComponentName, this);
- }
-
- if (mContexts == null) {
- mContexts = new ArrayList<>(1);
- }
-
- if (inlineSuggestionsRequest != null && !inlineSuggestionsRequest.isClientSupported()) {
- inlineSuggestionsRequest = null;
- }
-
- mClientSuggestionsSession.onFillRequest(requestId, inlineSuggestionsRequest, mFlags);
- }
-
/**
* The result of checking whether to show the save dialog, when session can be saved.
*
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 44307ef7..55b982b 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -21,7 +21,7 @@
name: "services.core-sources",
srcs: ["java/**/*.java"],
exclude_srcs: [
- ":services.core-sources-am-wm"
+ ":services.core-sources-am-wm",
],
path: "java",
visibility: [
@@ -38,13 +38,13 @@
],
tools: ["protologtool"],
cmd: "$(location protologtool) transform-protolog-calls " +
- "--protolog-class com.android.internal.protolog.common.ProtoLog " +
- "--protolog-impl-class com.android.internal.protolog.ProtoLogImpl " +
- "--protolog-cache-class 'com.android.server.wm.ProtoLogCache' " +
- "--loggroups-class com.android.internal.protolog.ProtoLogGroup " +
- "--loggroups-jar $(location :protolog-groups) " +
- "--output-srcjar $(out) " +
- "$(locations :services.core-sources-am-wm)",
+ "--protolog-class com.android.internal.protolog.common.ProtoLog " +
+ "--protolog-impl-class com.android.internal.protolog.ProtoLogImpl " +
+ "--protolog-cache-class 'com.android.server.wm.ProtoLogCache' " +
+ "--loggroups-class com.android.internal.protolog.ProtoLogGroup " +
+ "--loggroups-jar $(location :protolog-groups) " +
+ "--output-srcjar $(out) " +
+ "$(locations :services.core-sources-am-wm)",
out: ["services.core.protolog.srcjar"],
}
@@ -56,11 +56,11 @@
],
tools: ["protologtool"],
cmd: "$(location protologtool) generate-viewer-config " +
- "--protolog-class com.android.internal.protolog.common.ProtoLog " +
- "--loggroups-class com.android.internal.protolog.ProtoLogGroup " +
- "--loggroups-jar $(location :protolog-groups) " +
- "--viewer-conf $(out) " +
- "$(locations :services.core-sources-am-wm)",
+ "--protolog-class com.android.internal.protolog.common.ProtoLog " +
+ "--loggroups-class com.android.internal.protolog.ProtoLogGroup " +
+ "--loggroups-jar $(location :protolog-groups) " +
+ "--viewer-conf $(out) " +
+ "$(locations :services.core-sources-am-wm)",
out: ["services.core.protolog.json"],
}
@@ -71,12 +71,12 @@
":services.core.protolog.json",
],
cmd: "cp $(location :generate-protolog.json) $(out) && " +
- "{ ! (diff $(out) $(location :services.core.protolog.json) | grep -q '^<') || " +
- "{ echo -e '\\n\\n################################################################\\n#\\n" +
- "# ERROR: ProtoLog viewer config is stale. To update it, run:\\n#\\n" +
- "# cp $(location :generate-protolog.json) " +
- "$(location :services.core.protolog.json)\\n#\\n" +
- "################################################################\\n\\n' >&2 && false; } }",
+ "{ ! (diff $(out) $(location :services.core.protolog.json) | grep -q '^<') || " +
+ "{ echo -e '\\n\\n################################################################\\n#\\n" +
+ "# ERROR: ProtoLog viewer config is stale. To update it, run:\\n#\\n" +
+ "# cp $(location :generate-protolog.json) " +
+ "$(location :services.core.protolog.json)\\n#\\n" +
+ "################################################################\\n\\n' >&2 && false; } }",
out: ["services.core.protolog.json"],
}
@@ -84,7 +84,7 @@
name: "statslog-art-java-gen",
tools: ["stats-log-api-gen"],
cmd: "$(location stats-log-api-gen) --java $(out) --module art" +
- " --javaPackage com.android.internal.art --javaClass ArtStatsLog --worksource",
+ " --javaPackage com.android.internal.art --javaClass ArtStatsLog --worksource",
out: ["com/android/internal/art/ArtStatsLog.java"],
}
@@ -185,7 +185,7 @@
java_library_host {
name: "core_cts_test_resources",
- srcs: ["java/com/android/server/notification/SmallHash.java"]
+ srcs: ["java/com/android/server/notification/SmallHash.java"],
}
prebuilt_etc {
@@ -209,7 +209,6 @@
filegroup {
name: "services.core-sources-deviceconfig-interface",
srcs: [
- "java/com/android/server/utils/DeviceConfigInterface.java"
+ "java/com/android/server/utils/DeviceConfigInterface.java",
],
}
-
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index 76a6c0e..9299624 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -382,10 +382,10 @@
int deviceOwnerUserId, String deviceOwner, SparseArray<String> profileOwners);
/**
- * Called by DevicePolicyManagerService to set the package names protected by the device
- * owner.
+ * Called by Owners to set the package names protected by the device owner.
*/
- public abstract void setDeviceOwnerProtectedPackages(List<String> packageNames);
+ public abstract void setDeviceOwnerProtectedPackages(
+ String deviceOwnerPackageName, List<String> packageNames);
/**
* Returns {@code true} if a given package can't be wiped. Otherwise, returns {@code false}.
diff --git a/services/core/java/com/android/server/SensorPrivacyService.java b/services/core/java/com/android/server/SensorPrivacyService.java
index baec544..b0d6d65 100644
--- a/services/core/java/com/android/server/SensorPrivacyService.java
+++ b/services/core/java/com/android/server/SensorPrivacyService.java
@@ -61,6 +61,7 @@
import android.hardware.SensorPrivacyManager;
import android.hardware.SensorPrivacyManagerInternal;
import android.os.Binder;
+import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
@@ -72,10 +73,12 @@
import android.os.ShellCallback;
import android.os.ShellCommand;
import android.os.UserHandle;
+import android.os.UserManager;
import android.provider.Settings;
import android.service.SensorPrivacyIndividualEnabledSensorProto;
import android.service.SensorPrivacyServiceDumpProto;
import android.service.SensorPrivacyUserProto;
+import android.service.voice.VoiceInteractionManagerInternal;
import android.telephony.TelephonyCallback;
import android.telephony.TelephonyManager;
import android.telephony.emergency.EmergencyNumber;
@@ -172,6 +175,7 @@
mActivityManager = context.getSystemService(ActivityManager.class);
mActivityTaskManager = context.getSystemService(ActivityTaskManager.class);
mTelephonyManager = context.getSystemService(TelephonyManager.class);
+
mSensorPrivacyServiceImpl = new SensorPrivacyServiceImpl();
}
@@ -193,7 +197,7 @@
class SensorPrivacyServiceImpl extends ISensorPrivacyManager.Stub implements
AppOpsManager.OnOpNotedListener, AppOpsManager.OnOpStartedListener,
- IBinder.DeathRecipient {
+ IBinder.DeathRecipient, UserManagerInternal.UserRestrictionsListener {
private final SensorPrivacyHandler mHandler;
private final Object mLock = new Object();
@@ -280,6 +284,21 @@
}
}, new IntentFilter(ACTION_DISABLE_INDIVIDUAL_SENSOR_PRIVACY),
MANAGE_SENSOR_PRIVACY, null);
+ mUserManagerInternal.addUserRestrictionsListener(this);
+ }
+
+ @Override
+ public void onUserRestrictionsChanged(int userId, Bundle newRestrictions,
+ Bundle prevRestrictions) {
+ // Reset sensor privacy when restriction is added
+ if (!prevRestrictions.getBoolean(UserManager.DISALLOW_CAMERA_TOGGLE)
+ && newRestrictions.getBoolean(UserManager.DISALLOW_CAMERA_TOGGLE)) {
+ setIndividualSensorPrivacyUnchecked(userId, CAMERA, false);
+ }
+ if (!prevRestrictions.getBoolean(UserManager.DISALLOW_MICROPHONE_TOGGLE)
+ && newRestrictions.getBoolean(UserManager.DISALLOW_MICROPHONE_TOGGLE)) {
+ setIndividualSensorPrivacyUnchecked(userId, MICROPHONE, false);
+ }
}
@Override
@@ -402,6 +421,15 @@
}
}
+ VoiceInteractionManagerInternal voiceInteractionManagerInternal =
+ LocalServices.getService(VoiceInteractionManagerInternal.class);
+
+ if (sensor == MICROPHONE && voiceInteractionManagerInternal != null
+ && voiceInteractionManagerInternal.hasActiveSession(packageName)) {
+ enqueueSensorUseReminderDialogAsync(-1, user, packageName, sensor);
+ return;
+ }
+
Log.i(TAG, packageName + "/" + uid + " started using sensor " + sensor
+ " but no activity or foreground service was running. The user will not be"
+ " informed. System components should check if sensor privacy is enabled for"
@@ -608,6 +636,17 @@
return false;
}
+ if (sensor == MICROPHONE && mUserManagerInternal.getUserRestriction(userId,
+ UserManager.DISALLOW_MICROPHONE_TOGGLE)) {
+ Log.i(TAG, "Can't change mic toggle due to admin restriction");
+ return false;
+ }
+
+ if (sensor == CAMERA && mUserManagerInternal.getUserRestriction(userId,
+ UserManager.DISALLOW_CAMERA_TOGGLE)) {
+ Log.i(TAG, "Can't change camera toggle due to admin restriction");
+ return false;
+ }
return true;
}
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index a1a4418..69c2926 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -248,9 +248,18 @@
@Override
public void onUserSwitching(@Nullable TargetUser from, @NonNull TargetUser to) {
- mStorageManagerService.mCurrentUserId = to.getUserIdentifier();
- // To reset public volume mounts
- mStorageManagerService.onUserSwitching(mStorageManagerService.mCurrentUserId);
+ int currentUserId = to.getUserIdentifier();
+ mStorageManagerService.mCurrentUserId = currentUserId;
+
+ UserManagerInternal umInternal = LocalServices.getService(UserManagerInternal.class);
+ if (umInternal.isUserUnlocked(currentUserId)) {
+ Slog.d(TAG, "Attempt remount volumes for user: " + currentUserId);
+ mStorageManagerService.maybeRemountVolumes(currentUserId);
+ mStorageManagerService.mRemountCurrentUserVolumesOnUnlock = false;
+ } else {
+ Slog.d(TAG, "Attempt remount volumes for user: " + currentUserId + " on unlock");
+ mStorageManagerService.mRemountCurrentUserVolumesOnUnlock = true;
+ }
}
@Override
@@ -425,6 +434,8 @@
private volatile int mCurrentUserId = UserHandle.USER_SYSTEM;
+ private volatile boolean mRemountCurrentUserVolumesOnUnlock = false;
+
private final Installer mInstaller;
/** Holding lock for AppFuse business */
@@ -1196,6 +1207,10 @@
}
mHandler.obtainMessage(H_COMPLETE_UNLOCK_USER, userId).sendToTarget();
+ if (mRemountCurrentUserVolumesOnUnlock && userId == mCurrentUserId) {
+ maybeRemountVolumes(userId);
+ mRemountCurrentUserVolumesOnUnlock = false;
+ }
}
private void completeUnlockUser(int userId) {
@@ -1255,7 +1270,7 @@
}
}
- private void onUserSwitching(int userId) {
+ private void maybeRemountVolumes(int userId) {
boolean reset = false;
List<VolumeInfo> volumesToRemount = new ArrayList<>();
synchronized (mLock) {
@@ -1272,6 +1287,7 @@
}
for (VolumeInfo vol : volumesToRemount) {
+ Slog.i(TAG, "Remounting volume for user: " + userId + ". Volume: " + vol);
mHandler.obtainMessage(H_VOLUME_UNMOUNT, vol).sendToTarget();
mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
}
@@ -1850,7 +1866,7 @@
public StorageManagerService(Context context) {
sSelf = this;
mVoldAppDataIsolationEnabled = SystemProperties.getBoolean(
- ANDROID_VOLD_APP_DATA_ISOLATION_ENABLED_PROPERTY, true);
+ ANDROID_VOLD_APP_DATA_ISOLATION_ENABLED_PROPERTY, false);
mContext = context;
mResolver = mContext.getContentResolver();
mCallbacks = new Callbacks(FgThread.get().getLooper());
diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java
index 7a0a3a7..670f557 100644
--- a/services/core/java/com/android/server/Watchdog.java
+++ b/services/core/java/com/android/server/Watchdog.java
@@ -699,7 +699,7 @@
if (mActivity != null) {
mActivity.addErrorToDropBox(
"watchdog", null, "system_server", null, null, null,
- localSubject, report.toString(), stack, null, null, null);
+ localSubject, report.toString(), stack, null, null, null, null);
}
FrameworkStatsLog.write(FrameworkStatsLog.SYSTEM_SERVER_WATCHDOG_OCCURRED,
localSubject);
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index aadb25c..0f3aa65 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -16,6 +16,8 @@
package com.android.server.am;
+import static android.Manifest.permission.REQUEST_COMPANION_RUN_IN_BACKGROUND;
+import static android.Manifest.permission.REQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND;
import static android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND;
import static android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND;
import static android.app.ActivityManager.PROCESS_STATE_HEAVY_WEIGHT;
@@ -5831,6 +5833,26 @@
}
}
+ // Check for CDM apps with either REQUEST_COMPANION_RUN_IN_BACKGROUND or
+ // REQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND.
+ // Note: When a CDM app has REQUEST_COMPANION_RUN_IN_BACKGROUND, the app is also put
+ // in the user-allowlist. However, in this case, we want to use the reason code
+ // REASON_COMPANION_DEVICE_MANAGER, so this check needs to be before the
+ // isAllowlistedForFgsStartLOSP check.
+ if (ret == REASON_DENIED) {
+ final boolean isCompanionApp = mAm.mInternal.isAssociatedCompanionApp(
+ UserHandle.getUserId(callingUid), callingUid);
+ if (isCompanionApp) {
+ if (isPermissionGranted(
+ REQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND,
+ callingPid, callingUid)
+ || isPermissionGranted(REQUEST_COMPANION_RUN_IN_BACKGROUND,
+ callingPid, callingUid)) {
+ ret = REASON_COMPANION_DEVICE_MANAGER;
+ }
+ }
+ }
+
if (ret == REASON_DENIED) {
ActivityManagerService.FgsTempAllowListItem item =
mAm.isAllowlistedForFgsStartLOSP(callingUid);
@@ -5858,14 +5880,6 @@
}
if (ret == REASON_DENIED) {
- final boolean isCompanionApp = mAm.mInternal.isAssociatedCompanionApp(
- UserHandle.getUserId(callingUid), callingUid);
- if (isCompanionApp) {
- ret = REASON_COMPANION_DEVICE_MANAGER;
- }
- }
-
- if (ret == REASON_DENIED) {
final AppOpsManager appOpsManager = mAm.getAppOpsManager();
if (appOpsManager.checkOpNoThrow(AppOpsManager.OP_ACTIVATE_VPN, callingUid,
callingPackage) == AppOpsManager.MODE_ALLOWED) {
@@ -5884,6 +5898,10 @@
return ret;
}
+ private boolean isPermissionGranted(String permission, int callingPid, int callingUid) {
+ return mAm.checkPermission(permission, callingPid, callingUid) == PERMISSION_GRANTED;
+ }
+
private static boolean isFgsBgStart(@ReasonCode int code) {
return code != REASON_PROC_STATE_PERSISTENT
&& code != REASON_PROC_STATE_PERSISTENT_UI
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 5d1243b..d3955eb 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -421,6 +421,7 @@
import java.util.Locale;
import java.util.Map;
import java.util.Set;
+import java.util.UUID;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicInteger;
@@ -622,6 +623,8 @@
@GuardedBy("this")
BroadcastStats mCurBroadcastStats;
+ TraceErrorLogger mTraceErrorLogger;
+
BroadcastQueue broadcastQueueForIntent(Intent intent) {
if (isOnOffloadQueue(intent.getFlags())) {
if (DEBUG_BROADCAST_BACKGROUND) {
@@ -2337,6 +2340,7 @@
mInternal = new LocalService();
mPendingStartActivityUids = new PendingStartActivityUids(mContext);
+ mTraceErrorLogger = new TraceErrorLogger();
}
public void setSystemServiceManager(SystemServiceManager mgr) {
@@ -7811,7 +7815,7 @@
addErrorToDropBox(
eventType, r, processName, null, null, null, null, null, null, crashInfo,
- new Float(loadingProgress), incrementalMetrics);
+ new Float(loadingProgress), incrementalMetrics, null);
mAppErrors.crashApplication(r, crashInfo);
}
@@ -7994,7 +7998,7 @@
callingPid, (r != null) ? r.getProcessClassEnum() : 0);
addErrorToDropBox("wtf", r, processName, null, null, null, tag, null, null, crashInfo,
- null, null);
+ null, null, null);
return r;
}
@@ -8019,7 +8023,7 @@
for (Pair<String, ApplicationErrorReport.CrashInfo> p = list.poll();
p != null; p = list.poll()) {
addErrorToDropBox("wtf", proc, "system_server", null, null, null, p.first, null, null,
- p.second, null, null);
+ p.second, null, null, null);
}
}
@@ -8110,13 +8114,15 @@
* @param crashInfo giving an application stack trace, null if absent
* @param loadingProgress the loading progress of an installed package, range in [0, 1].
* @param incrementalMetrics metrics for apps installed on Incremental.
+ * @param errorId a unique id to append to the dropbox headers.
*/
public void addErrorToDropBox(String eventType,
ProcessRecord process, String processName, String activityShortComponentName,
String parentShortComponentName, ProcessRecord parentProcess,
String subject, final String report, final File dataFile,
final ApplicationErrorReport.CrashInfo crashInfo,
- @Nullable Float loadingProgress, @Nullable IncrementalMetrics incrementalMetrics) {
+ @Nullable Float loadingProgress, @Nullable IncrementalMetrics incrementalMetrics,
+ @Nullable UUID errorId) {
// NOTE -- this must never acquire the ActivityManagerService lock,
// otherwise the watchdog may be prevented from resetting the system.
@@ -8170,6 +8176,9 @@
if (subject != null) {
sb.append("Subject: ").append(subject).append("\n");
}
+ if (errorId != null) {
+ sb.append("ErrorId: ").append(errorId.toString()).append("\n");
+ }
sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
if (Debug.isDebuggerConnected()) {
sb.append("Debugger: Connected\n");
diff --git a/services/core/java/com/android/server/am/AppProfiler.java b/services/core/java/com/android/server/am/AppProfiler.java
index 074e8fe..74094e5 100644
--- a/services/core/java/com/android/server/am/AppProfiler.java
+++ b/services/core/java/com/android/server/am/AppProfiler.java
@@ -1627,7 +1627,7 @@
dropBuilder.append(catSw.toString());
FrameworkStatsLog.write(FrameworkStatsLog.LOW_MEM_REPORTED);
mService.addErrorToDropBox("lowmem", null, "system_server", null,
- null, null, tag.toString(), dropBuilder.toString(), null, null, null, null);
+ null, null, tag.toString(), dropBuilder.toString(), null, null, null, null, null);
synchronized (mService) {
long now = SystemClock.uptimeMillis();
if (mLastMemUsageReportTime < now) {
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 5937a18..610884f 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -468,7 +468,7 @@
synchronized (mStats) {
mStats.notePowerSaveModeLocked(
powerMgr.getLowPowerState(ServiceType.BATTERY_STATS).batterySaverEnabled,
- SystemClock.elapsedRealtime(), SystemClock.uptimeMillis());
+ SystemClock.elapsedRealtime(), SystemClock.uptimeMillis(), true);
}
(new WakeupReasonThread()).start();
}
@@ -511,7 +511,7 @@
mHandler.post(() -> {
synchronized (mStats) {
mStats.notePowerSaveModeLocked(result.batterySaverEnabled,
- elapsedRealtime, uptime);
+ elapsedRealtime, uptime, false);
}
});
}
diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java
index 709139e..4629d0b 100644
--- a/services/core/java/com/android/server/am/CachedAppOptimizer.java
+++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java
@@ -881,7 +881,10 @@
@GuardedBy({"mAm", "mProcLock"})
void freezeAppAsyncLSP(ProcessRecord app) {
- mFreezeHandler.removeMessages(SET_FROZEN_PROCESS_MSG, app);
+ if (mFreezeHandler.hasMessages(SET_FROZEN_PROCESS_MSG, app)) {
+ // Skip redundant DO_FREEZE message
+ return;
+ }
mFreezeHandler.sendMessageDelayed(
mFreezeHandler.obtainMessage(
diff --git a/services/core/java/com/android/server/am/ErrorDialogController.java b/services/core/java/com/android/server/am/ErrorDialogController.java
index f23d309..a4e8f92 100644
--- a/services/core/java/com/android/server/am/ErrorDialogController.java
+++ b/services/core/java/com/android/server/am/ErrorDialogController.java
@@ -115,7 +115,7 @@
return;
}
if (needDismiss) {
- forAllDialogs(mCrashDialogs, Dialog::dismiss);
+ scheduleForAllDialogs(mCrashDialogs, Dialog::dismiss);
}
mCrashDialogs = null;
}
@@ -125,7 +125,7 @@
if (mAnrDialogs == null) {
return;
}
- forAllDialogs(mAnrDialogs, Dialog::dismiss);
+ scheduleForAllDialogs(mAnrDialogs, Dialog::dismiss);
mAnrDialogs = null;
mAnrController = null;
}
@@ -135,7 +135,7 @@
if (mViolationDialogs == null) {
return;
}
- forAllDialogs(mViolationDialogs, Dialog::dismiss);
+ scheduleForAllDialogs(mViolationDialogs, Dialog::dismiss);
mViolationDialogs = null;
}
@@ -148,6 +148,16 @@
mWaitDialog = null;
}
+ @GuardedBy("mProcLock")
+ void scheduleForAllDialogs(List<? extends BaseErrorDialog> dialogs,
+ Consumer<BaseErrorDialog> c) {
+ mService.mUiHandler.post(() -> {
+ if (dialogs != null) {
+ forAllDialogs(dialogs, c);
+ }
+ });
+ }
+
void forAllDialogs(List<? extends BaseErrorDialog> dialogs, Consumer<BaseErrorDialog> c) {
for (int i = dialogs.size() - 1; i >= 0; i--) {
c.accept(dialogs.get(i));
@@ -182,15 +192,7 @@
final Context c = contexts.get(i);
mAnrDialogs.add(new AppNotRespondingDialog(mService, c, data));
}
- mService.mUiHandler.post(() -> {
- List<AppNotRespondingDialog> dialogs;
- synchronized (mProcLock) {
- dialogs = mAnrDialogs;
- }
- if (dialogs != null) {
- forAllDialogs(dialogs, Dialog::show);
- }
- });
+ scheduleForAllDialogs(mAnrDialogs, Dialog::show);
}
@GuardedBy("mProcLock")
@@ -202,15 +204,7 @@
mViolationDialogs.add(
new StrictModeViolationDialog(c, mService, res, mApp));
}
- mService.mUiHandler.post(() -> {
- List<StrictModeViolationDialog> dialogs;
- synchronized (mProcLock) {
- dialogs = mViolationDialogs;
- }
- if (dialogs != null) {
- forAllDialogs(dialogs, Dialog::show);
- }
- });
+ scheduleForAllDialogs(mViolationDialogs, Dialog::show);
}
@GuardedBy("mProcLock")
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 01bbb03..4ad9909 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -511,6 +511,7 @@
final ProcessRecord topApp = mService.getTopApp();
final ProcessStateRecord state = app.mState;
final boolean wasCached = state.isCached();
+ final int oldCap = state.getSetCapability();
mAdjSeq++;
@@ -526,6 +527,7 @@
SystemClock.uptimeMillis());
if (oomAdjAll
&& (wasCached != state.isCached()
+ || oldCap != state.getSetCapability()
|| state.getCurRawAdj() == ProcessList.UNKNOWN_ADJ)) {
// Changed to/from cached state, so apps after it in the LRU
// list may also be changed.
@@ -663,6 +665,7 @@
? oldAdj : ProcessList.UNKNOWN_ADJ;
final boolean wasBackground = ActivityManager.isProcStateBackground(
state.getSetProcState());
+ final int oldCap = state.getSetCapability();
state.setContainsCycle(false);
state.setProcStateChanged(false);
state.resetCachedInfo();
@@ -671,6 +674,7 @@
boolean success = performUpdateOomAdjLSP(app, cachedAdj, topApp, false,
SystemClock.uptimeMillis());
if (!success || (wasCached == state.isCached() && oldAdj != ProcessList.INVALID_ADJ
+ && oldCap == state.getCurCapability()
&& wasBackground == ActivityManager.isProcStateBackground(
state.getSetProcState()))) {
// Okay, it's unchanged, it won't impact any service it binds to, we're done here.
@@ -685,20 +689,62 @@
// Next to find out all its reachable processes
ArrayList<ProcessRecord> processes = mTmpProcessList;
ActiveUids uids = mTmpUidRecords;
- ArrayDeque<ProcessRecord> queue = mTmpQueue;
+ mPendingProcessSet.add(app);
+ boolean containsCycle = collectReachableProcessesLocked(mPendingProcessSet,
+ processes, uids);
+
+ // Clear the pending set as they should've been included in 'processes'.
+ mPendingProcessSet.clear();
+ // Reset the flag
+ state.setReachable(false);
+ // Remove this app from the return list because we've done the computation on it.
+ processes.remove(app);
+
+ int size = processes.size();
+ if (size > 0) {
+ mAdjSeq--;
+ // Update these reachable processes
+ updateOomAdjInnerLSP(oomAdjReason, topApp, processes, uids, containsCycle, false);
+ } else if (state.getCurRawAdj() == ProcessList.UNKNOWN_ADJ) {
+ // In case the app goes from non-cached to cached but it doesn't have other reachable
+ // processes, its adj could be still unknown as of now, assign one.
+ processes.add(app);
+ assignCachedAdjIfNecessary(processes);
+ applyOomAdjLSP(app, false, SystemClock.uptimeMillis(),
+ SystemClock.elapsedRealtime());
+ }
+ mTmpProcessList.clear();
+ mService.mOomAdjProfiler.oomAdjEnded();
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+ return true;
+ }
+
+ @GuardedBy("mService")
+ private boolean collectReachableProcessesLocked(ArraySet<ProcessRecord> apps,
+ ArrayList<ProcessRecord> processes, ActiveUids uids) {
+ final ArrayDeque<ProcessRecord> queue = mTmpQueue;
+ queue.clear();
+ for (int i = 0, size = apps.size(); i < size; i++) {
+ final ProcessRecord app = apps.valueAt(i);
+ app.mState.setReachable(true);
+ queue.offer(app);
+ }
+
+ return collectReachableProcessesLocked(queue, processes, uids);
+ }
+
+ @GuardedBy("mService")
+ private boolean collectReachableProcessesLocked(ArrayDeque<ProcessRecord> queue,
+ ArrayList<ProcessRecord> processes, ActiveUids uids) {
processes.clear();
uids.clear();
- queue.clear();
// Track if any of them reachables could include a cycle
boolean containsCycle = false;
// Scan downstreams of the process record
- state.setReachable(true);
- for (ProcessRecord pr = app; pr != null; pr = queue.poll()) {
- if (pr != app) {
- processes.add(pr);
- }
+ for (ProcessRecord pr = queue.poll(); pr != null; pr = queue.poll()) {
+ processes.add(pr);
final UidRecord uidRec = pr.getUidRecord();
if (uidRec != null) {
uids.put(uidRec.getUid(), uidRec);
@@ -723,10 +769,6 @@
}
queue.offer(service);
service.mState.setReachable(true);
- // During scanning the reachable dependants, remove them from the pending oomadj
- // targets list if it's possible, as they've been added into the immediate
- // oomadj targets list 'processes' above.
- mPendingProcessSet.remove(service);
}
final ProcessProviderRecord ppr = pr.mProviders;
for (int i = ppr.numberOfProviderConnections() - 1; i >= 0; i--) {
@@ -742,15 +784,9 @@
}
queue.offer(provider);
provider.mState.setReachable(true);
- // During scanning the reachable dependants, remove them from the pending oomadj
- // targets list if it's possible, as they've been added into the immediate
- // oomadj targets list 'processes' above.
- mPendingProcessSet.remove(provider);
}
}
- // Reset the flag
- state.setReachable(false);
int size = processes.size();
if (size > 0) {
// Reverse the process list, since the updateOomAdjInnerLSP scans from the end of it.
@@ -759,21 +795,8 @@
processes.set(l, processes.get(r));
processes.set(r, t);
}
- mAdjSeq--;
- // Update these reachable processes
- updateOomAdjInnerLSP(oomAdjReason, topApp, processes, uids, containsCycle, false);
- } else if (state.getCurRawAdj() == ProcessList.UNKNOWN_ADJ) {
- // In case the app goes from non-cached to cached but it doesn't have other reachable
- // processes, its adj could be still unknown as of now, assign one.
- processes.add(app);
- assignCachedAdjIfNecessary(processes);
- applyOomAdjLSP(app, false, SystemClock.uptimeMillis(),
- SystemClock.elapsedRealtime());
}
- mTmpProcessList.clear();
- mService.mOomAdjProfiler.oomAdjEnded();
- Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
- return true;
+ return containsCycle;
}
/**
@@ -857,22 +880,12 @@
final ArrayList<ProcessRecord> processes = mTmpProcessList;
final ActiveUids uids = mTmpUidRecords;
+ collectReachableProcessesLocked(mPendingProcessSet, processes, uids);
+ mPendingProcessSet.clear();
synchronized (mProcLock) {
- uids.clear();
- processes.clear();
- for (int i = mPendingProcessSet.size() - 1; i >= 0; i--) {
- final ProcessRecord app = mPendingProcessSet.valueAt(i);
- final UidRecord uidRec = app.getUidRecord();
- if (uidRec != null) {
- uids.put(uidRec.getUid(), uidRec);
- }
- processes.add(app);
- }
-
updateOomAdjInnerLSP(oomAdjReason, topApp, processes, uids, true, false);
}
processes.clear();
- mPendingProcessSet.clear();
mService.mOomAdjProfiler.oomAdjEnded();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
diff --git a/services/core/java/com/android/server/am/ProcessErrorStateRecord.java b/services/core/java/com/android/server/am/ProcessErrorStateRecord.java
index 88bd010..66d4779 100644
--- a/services/core/java/com/android/server/am/ProcessErrorStateRecord.java
+++ b/services/core/java/com/android/server/am/ProcessErrorStateRecord.java
@@ -55,7 +55,7 @@
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
-
+import java.util.UUID;
/**
* The error state of the process, such as if it's crashing/ANR etc.
*/
@@ -235,6 +235,7 @@
final boolean isSilentAnr;
final int pid = mApp.getPid();
+ final UUID errorId;
synchronized (mService) {
// PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
if (mService.mAtmInternal.isShuttingDown()) {
@@ -264,6 +265,13 @@
EventLog.writeEvent(EventLogTags.AM_ANR, mApp.userId, pid, mApp.processName,
mApp.info.flags, annotation);
+ if (mService.mTraceErrorLogger.isAddErrorIdEnabled()) {
+ errorId = mService.mTraceErrorLogger.generateErrorId();
+ mService.mTraceErrorLogger.addErrorIdToTrace(errorId);
+ } else {
+ errorId = null;
+ }
+
// Dump thread traces as quickly as we can, starting with "interesting" processes.
firstPids.add(pid);
@@ -315,6 +323,9 @@
&& parentShortComponentName.equals(activityShortComponentName)) {
info.append("Parent: ").append(parentShortComponentName).append("\n");
}
+ if (errorId != null) {
+ info.append("ErrorId: ").append(errorId.toString()).append("\n");
+ }
// Retrieve controller with max ANR delay from AnrControllers
// Note that we retrieve the controller before dumping stacks because dumping stacks can
@@ -457,7 +468,7 @@
? (ProcessRecord) parentProcess.mOwner : null;
mService.addErrorToDropBox("anr", mApp, mApp.processName, activityShortComponentName,
parentShortComponentName, parentPr, annotation, report.toString(), tracesFile,
- null, new Float(loadingProgress), incrementalMetrics);
+ null, new Float(loadingProgress), incrementalMetrics, errorId);
if (mApp.getWindowProcessController().appNotResponding(info.toString(),
() -> {
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 0d19209e..0ffaccf 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -802,7 +802,7 @@
mAppDataIsolationEnabled =
SystemProperties.getBoolean(ANDROID_APP_DATA_ISOLATION_ENABLED_PROPERTY, true);
mVoldAppDataIsolationEnabled = SystemProperties.getBoolean(
- ANDROID_VOLD_APP_DATA_ISOLATION_ENABLED_PROPERTY, true);
+ ANDROID_VOLD_APP_DATA_ISOLATION_ENABLED_PROPERTY, false);
mAppDataIsolationAllowlistedApps = new ArrayList<>(
SystemConfig.getInstance().getAppDataIsolationWhitelistedApps());
diff --git a/services/core/java/com/android/server/am/ProcessStateRecord.java b/services/core/java/com/android/server/am/ProcessStateRecord.java
index 6429b79..801e382 100644
--- a/services/core/java/com/android/server/am/ProcessStateRecord.java
+++ b/services/core/java/com/android/server/am/ProcessStateRecord.java
@@ -25,7 +25,6 @@
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.os.PowerWhitelistManager.REASON_BACKGROUND_ACTIVITY_PERMISSION;
import static android.os.PowerWhitelistManager.REASON_BACKGROUND_FGS_PERMISSION;
-import static android.os.PowerWhitelistManager.REASON_COMPANION_DEVICE_MANAGER;
import static android.os.PowerWhitelistManager.REASON_DENIED;
import static android.os.PowerWhitelistManager.REASON_DEVICE_OWNER;
import static android.os.PowerWhitelistManager.REASON_PROFILE_OWNER;
@@ -1217,6 +1216,7 @@
mAllowStartFgs = mAllowStartFgsByPermission = ret;
}
+ // TODO(b/188063200) Clean up this method. Why do we need to duplicate only some of the checks?
@GuardedBy("mService")
void setAllowStartFgs() {
if (mAllowStartFgs != REASON_DENIED) {
@@ -1238,16 +1238,6 @@
}
if (mAllowStartFgs == REASON_DENIED) {
- if (mService.mInternal != null) {
- final boolean isCompanionApp = mService.mInternal.isAssociatedCompanionApp(
- UserHandle.getUserId(mApp.info.uid), mApp.info.uid);
- if (isCompanionApp) {
- mAllowStartFgs = REASON_COMPANION_DEVICE_MANAGER;
- }
- }
- }
-
- if (mAllowStartFgs == REASON_DENIED) {
// Is the calling UID a profile owner app?
if (mService.mInternal != null) {
if (mService.mInternal.isProfileOwner(mApp.info.uid)) {
diff --git a/services/core/java/com/android/server/am/TraceErrorLogger.java b/services/core/java/com/android/server/am/TraceErrorLogger.java
new file mode 100644
index 0000000..f055be2
--- /dev/null
+++ b/services/core/java/com/android/server/am/TraceErrorLogger.java
@@ -0,0 +1,58 @@
+/*
+ * 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.am;
+
+import android.os.Trace;
+import android.provider.DeviceConfig;
+
+import java.util.UUID;
+
+/**
+ * Adds a unique id to a trace.
+ *
+ * @hide
+ */
+class TraceErrorLogger {
+ private static final String COUNTER_PREFIX = "ErrorId:";
+ private static final String ADD_ERROR_ID = "add_error_id";
+ private static final int PLACEHOLDER_VALUE = 1;
+
+ public boolean isAddErrorIdEnabled() {
+ return DeviceConfig
+ .getBoolean(DeviceConfig.NAMESPACE_TRACE_ERROR_LOGGER, ADD_ERROR_ID,
+ false);
+ }
+
+ /**
+ * Generates a unique id with which to tag a trace.
+ */
+ public UUID generateErrorId() {
+ return UUID.randomUUID();
+ }
+
+ /**
+ * Pushes a counter containing a unique id and a label {@link #COUNTER_PREFIX} so that traces
+ * can be uniquely identified. We also add the same id to the dropbox entry of the error, so
+ * that we can join the trace and the error server-side.
+ *
+ * @param errorId The unique id with which to tag the trace.
+ */
+ public void addErrorIdToTrace(UUID errorId) {
+ Trace.traceCounter(Trace.TRACE_TAG_ACTIVITY_MANAGER, COUNTER_PREFIX + errorId.toString(),
+ PLACEHOLDER_VALUE);
+ }
+}
diff --git a/services/core/java/com/android/server/app/GameManagerService.java b/services/core/java/com/android/server/app/GameManagerService.java
index d2c6c6c..1aeeda0 100644
--- a/services/core/java/com/android/server/app/GameManagerService.java
+++ b/services/core/java/com/android/server/app/GameManagerService.java
@@ -56,7 +56,6 @@
import android.provider.DeviceConfig;
import android.provider.DeviceConfig.Properties;
import android.util.ArrayMap;
-import android.util.ArraySet;
import android.util.KeyValueListParser;
import android.util.Slog;
@@ -363,19 +362,42 @@
|| (mPerfModeOptedIn && gameMode == GameManager.GAME_MODE_PERFORMANCE);
}
- public @GameMode int[] getAvailableGameModes() {
- ArraySet<Integer> modeSet = new ArraySet<>(mModeConfigs.keySet());
+ private int getAvailableGameModesBitfield() {
+ int field = 0;
+ for (final int mode : mModeConfigs.keySet()) {
+ field |= modeToBitmask(mode);
+ }
if (mBatteryModeOptedIn) {
- modeSet.add(GameManager.GAME_MODE_BATTERY);
+ field |= modeToBitmask(GameManager.GAME_MODE_BATTERY);
}
if (mPerfModeOptedIn) {
- modeSet.add(GameManager.GAME_MODE_PERFORMANCE);
+ field |= modeToBitmask(GameManager.GAME_MODE_PERFORMANCE);
}
- if (modeSet.size() > 0) {
- modeSet.add(GameManager.GAME_MODE_STANDARD);
- return modeSet.stream().mapToInt(Integer::intValue).toArray();
+ // The lowest bit is reserved for UNSUPPORTED, STANDARD is supported if we support any
+ // other mode.
+ if (field > 1) {
+ field |= modeToBitmask(GameManager.GAME_MODE_STANDARD);
+ } else {
+ field |= modeToBitmask(GameManager.GAME_MODE_UNSUPPORTED);
}
- return new int[]{GameManager.GAME_MODE_UNSUPPORTED};
+ return field;
+ }
+
+ /**
+ * Get an array of a package's available game modes.
+ */
+ public @GameMode int[] getAvailableGameModes() {
+
+ int modesBitfield = getAvailableGameModesBitfield();
+ int sigBits = Integer.bitCount(modesBitfield);
+ int[] modes = new int[sigBits];
+ int i = 0;
+ for (int mode = 0; mode < sigBits; ++mode) {
+ if (((modesBitfield >> mode) & 1) != 0) {
+ modes[i++] = mode;
+ }
+ }
+ return modes;
}
/**
@@ -696,6 +718,14 @@
}
}
+ private int modeToBitmask(@GameMode int gameMode) {
+ return (1 << gameMode);
+ }
+
+ private boolean bitFieldContainsModeBitmask(int bitField, @GameMode int gameMode) {
+ return (bitField & modeToBitmask(gameMode)) != 0;
+ }
+
/**
* @hide
*/
@@ -703,8 +733,8 @@
public void updateConfigsForUser(int userId, String ...packageNames) {
try {
synchronized (mDeviceConfigLock) {
- for (String packageName : packageNames) {
- GamePackageConfiguration config =
+ for (final String packageName : packageNames) {
+ final GamePackageConfiguration config =
new GamePackageConfiguration(packageName, userId);
if (config.isValid()) {
if (DEBUG) {
@@ -718,13 +748,42 @@
}
}
}
- for (String packageName : packageNames) {
- synchronized (mLock) {
- if (mSettings.containsKey(userId)) {
- GameManagerSettings userSettings = mSettings.get(userId);
- updateCompatModeDownscale(packageName,
- userSettings.getGameModeLocked(packageName));
+ for (final String packageName : packageNames) {
+ if (mSettings.containsKey(userId)) {
+ int gameMode = getGameMode(packageName, userId);
+ int newGameMode = gameMode;
+ // Make sure the user settings and package configs don't conflict. I.e. the
+ // user setting is set to a mode that no longer available due to config/manifest
+ // changes. Most of the time we won't have to change anything.
+ GamePackageConfiguration config;
+ synchronized (mDeviceConfigLock) {
+ config = mConfigs.get(packageName);
}
+ if (config != null) {
+ int modesBitfield = config.getAvailableGameModesBitfield();
+ // Remove UNSUPPORTED to simplify the logic here, since we really just
+ // want to check if we support selectable game modes
+ modesBitfield &= ~modeToBitmask(GameManager.GAME_MODE_UNSUPPORTED);
+ if (!bitFieldContainsModeBitmask(modesBitfield, gameMode)) {
+ if (bitFieldContainsModeBitmask(modesBitfield,
+ GameManager.GAME_MODE_STANDARD)) {
+ // If the current set mode isn't supported, but we support STANDARD,
+ // then set the mode to STANDARD.
+ newGameMode = GameManager.GAME_MODE_STANDARD;
+ } else {
+ // If we don't support any game modes, then set to UNSUPPORTED
+ newGameMode = GameManager.GAME_MODE_UNSUPPORTED;
+ }
+ }
+ } else if (gameMode != GameManager.GAME_MODE_UNSUPPORTED) {
+ // If we have no config for the package, but the configured mode is not
+ // UNSUPPORTED, then set to UNSUPPORTED
+ newGameMode = GameManager.GAME_MODE_UNSUPPORTED;
+ }
+ if (newGameMode != gameMode) {
+ setGameMode(packageName, newGameMode, userId);
+ }
+ updateCompatModeDownscale(packageName, gameMode);
}
}
} catch (Exception e) {
diff --git a/services/core/java/com/android/server/apphibernation/AppHibernationService.java b/services/core/java/com/android/server/apphibernation/AppHibernationService.java
index 05c4431..535fb67 100644
--- a/services/core/java/com/android/server/apphibernation/AppHibernationService.java
+++ b/services/core/java/com/android/server/apphibernation/AppHibernationService.java
@@ -220,9 +220,9 @@
final Map<String, UserLevelState> packageStates = mUserStates.get(userId);
final UserLevelState pkgState = packageStates.get(packageName);
if (pkgState == null) {
- throw new IllegalArgumentException(
- String.format("Package %s is not installed for user %s",
- packageName, userId));
+ Slog.e(TAG, String.format("Package %s is not installed for user %s",
+ packageName, userId));
+ return false;
}
return pkgState.hibernated;
}
@@ -275,9 +275,9 @@
final Map<String, UserLevelState> packageStates = mUserStates.get(userId);
final UserLevelState pkgState = packageStates.get(packageName);
if (pkgState == null) {
- throw new IllegalArgumentException(
- String.format("Package %s is not installed for user %s",
- packageName, userId));
+ Slog.e(TAG, String.format("Package %s is not installed for user %s",
+ packageName, userId));
+ return;
}
if (pkgState.hibernated == isHibernating) {
@@ -320,8 +320,8 @@
synchronized (mLock) {
GlobalLevelState state = mGlobalHibernationStates.get(packageName);
if (state == null) {
- throw new IllegalArgumentException(
- String.format("Package %s is not installed for any user", packageName));
+ Slog.e(TAG, String.format("Package %s is not installed for any user", packageName));
+ return;
}
if (state.hibernated != isHibernating) {
if (isHibernating) {
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 76abfbf..b6aec836 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -1085,7 +1085,7 @@
}
// no need to record a paused event finishing.
- InProgressStartOpEvent event = mInProgressEvents.valueAt(indexOfToken);
+ InProgressStartOpEvent event = mPausedInProgressEvents.valueAt(indexOfToken);
event.numUnfinishedStarts--;
if (event.numUnfinishedStarts == 0) {
mPausedInProgressEvents.removeAt(indexOfToken);
@@ -1282,6 +1282,10 @@
return mInProgressEvents != null;
}
+ public boolean isPaused() {
+ return mPausedInProgressEvents != null;
+ }
+
boolean hasAnyTime() {
return (mAccessEvents != null && mAccessEvents.size() > 0)
|| (mRejectEvents != null && mRejectEvents.size() > 0);
@@ -3957,7 +3961,7 @@
return;
}
- if (attributedOp.isRunning()) {
+ if (attributedOp.isRunning() || attributedOp.isPaused()) {
attributedOp.finished(clientId);
} else {
Slog.e(TAG, "Operation not started: uid=" + uid + " pkg=" + packageName + "("
@@ -6466,6 +6470,7 @@
"offsetHistory");
// Must not hold the appops lock
mHistoricalRegistry.offsetHistory(offsetMillis);
+ mHistoricalRegistry.offsetDiscreteHistory(offsetMillis);
}
@Override
diff --git a/services/core/java/com/android/server/appop/DiscreteRegistry.java b/services/core/java/com/android/server/appop/DiscreteRegistry.java
index fc48b3f..99daa24 100644
--- a/services/core/java/com/android/server/appop/DiscreteRegistry.java
+++ b/services/core/java/com/android/server/appop/DiscreteRegistry.java
@@ -27,6 +27,8 @@
import static android.app.AppOpsManager.OP_FLAG_SELF;
import static android.app.AppOpsManager.OP_FLAG_TRUSTED_PROXIED;
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;
import static android.app.AppOpsManager.OP_RECORD_AUDIO;
import static android.app.AppOpsManager.flagsToString;
import static android.app.AppOpsManager.getUidStateName;
@@ -122,7 +124,8 @@
private static final String PROPERTY_DISCRETE_FLAGS = "discrete_history_op_flags";
private static final String PROPERTY_DISCRETE_OPS_LIST = "discrete_history_ops_cslist";
private static final String DEFAULT_DISCRETE_OPS = OP_FINE_LOCATION + "," + OP_COARSE_LOCATION
- + "," + OP_CAMERA + "," + OP_RECORD_AUDIO;
+ + "," + OP_CAMERA + "," + OP_RECORD_AUDIO + "," + OP_PHONE_CALL_MICROPHONE + ","
+ + OP_PHONE_CALL_CAMERA;
private static final long DEFAULT_DISCRETE_HISTORY_CUTOFF = Duration.ofHours(24).toMillis();
private static final long MAXIMUM_DISCRETE_HISTORY_CUTOFF = Duration.ofDays(30).toMillis();
private static final long DEFAULT_DISCRETE_HISTORY_QUANTIZATION =
diff --git a/services/core/java/com/android/server/appop/HistoricalRegistry.java b/services/core/java/com/android/server/appop/HistoricalRegistry.java
index 35e8d34..0ab6c4a 100644
--- a/services/core/java/com/android/server/appop/HistoricalRegistry.java
+++ b/services/core/java/com/android/server/appop/HistoricalRegistry.java
@@ -212,6 +212,7 @@
}
void systemReady(@NonNull ContentResolver resolver) {
+ mDiscreteRegistry.systemReady();
final Uri uri = Settings.Global.getUriFor(Settings.Global.APPOP_HISTORY_PARAMETERS);
resolver.registerContentObserver(uri, false, new ContentObserver(
FgThread.getHandler()) {
@@ -249,7 +250,6 @@
}
}
}
- mDiscreteRegistry.systemReady();
}
private boolean isPersistenceInitializedMLocked() {
@@ -594,6 +594,9 @@
mPersistence.persistHistoricalOpsDLocked(history);
}
}
+ }
+
+ void offsetDiscreteHistory(long offsetMillis) {
mDiscreteRegistry.offsetHistory(offsetMillis);
}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index a3c5904..136916a 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -413,6 +413,26 @@
AudioSystem.STREAM_MUSIC, // STREAM_ACCESSIBILITY
AudioSystem.STREAM_MUSIC // STREAM_ASSISTANT
};
+ /**
+ * Using Volume groups configuration allows to control volume per attributes
+ * and group definition may differ from stream aliases.
+ * So, do not alias any stream on one another when using volume groups.
+ * TODO(b/181140246): volume group definition hosting alias definition.
+ */
+ private final int[] STREAM_VOLUME_ALIAS_NONE = new int[] {
+ AudioSystem.STREAM_VOICE_CALL, // STREAM_VOICE_CALL
+ AudioSystem.STREAM_SYSTEM, // STREAM_SYSTEM
+ AudioSystem.STREAM_RING, // STREAM_RING
+ AudioSystem.STREAM_MUSIC, // STREAM_MUSIC
+ AudioSystem.STREAM_ALARM, // STREAM_ALARM
+ AudioSystem.STREAM_NOTIFICATION, // STREAM_NOTIFICATION
+ AudioSystem.STREAM_BLUETOOTH_SCO, // STREAM_BLUETOOTH_SCO
+ AudioSystem.STREAM_SYSTEM_ENFORCED, // STREAM_SYSTEM_ENFORCED
+ AudioSystem.STREAM_DTMF, // STREAM_DTMF
+ AudioSystem.STREAM_TTS, // STREAM_TTS
+ AudioSystem.STREAM_ACCESSIBILITY, // STREAM_ACCESSIBILITY
+ AudioSystem.STREAM_ASSISTANT // STREAM_ASSISTANT
+ };
private final int[] STREAM_VOLUME_ALIAS_DEFAULT = new int[] {
AudioSystem.STREAM_VOICE_CALL, // STREAM_VOICE_CALL
AudioSystem.STREAM_RING, // STREAM_SYSTEM
@@ -428,6 +448,7 @@
AudioSystem.STREAM_MUSIC // STREAM_ASSISTANT
};
protected static int[] mStreamVolumeAlias;
+ private static final int UNSET_INDEX = -1;
/**
* Map AudioSystem.STREAM_* constants to app ops. This should be used
@@ -449,6 +470,7 @@
};
private final boolean mUseFixedVolume;
+ private final boolean mUseVolumeGroupAliases;
// If absolute volume is supported in AVRCP device
private volatile boolean mAvrcpAbsVolSupported = false;
@@ -849,6 +871,9 @@
mSupportsMicPrivacyToggle = context.getSystemService(SensorPrivacyManager.class)
.supportsSensorToggle(SensorPrivacyManager.Sensors.MICROPHONE);
+ mUseVolumeGroupAliases = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_handleVolumeAliasesUsingVolumeGroups);
+
// Initialize volume
// Priority 1 - Android Property
// Priority 2 - Audio Policy Service
@@ -869,6 +894,12 @@
MIN_STREAM_VOLUME[streamType] = minVolume;
}
}
+ if (mUseVolumeGroupAliases) {
+ // Set all default to uninitialized.
+ for (int stream = 0; stream < AudioSystem.DEFAULT_STREAM_VOLUME.length; stream++) {
+ AudioSystem.DEFAULT_STREAM_VOLUME[stream] = UNSET_INDEX;
+ }
+ }
}
int maxCallVolume = SystemProperties.getInt("ro.config.vc_call_vol_steps", -1);
@@ -1705,18 +1736,42 @@
updateDefaultVolumes();
}
- // Update default indexes from aliased streams. Must be called after mStreamStates is created
+ /**
+ * Update default indexes from aliased streams. Must be called after mStreamStates is created
+ * TODO(b/181140246): when using VolumeGroup alias, we are lacking configurability for default
+ * index. Need to make default index configurable and independent of streams.
+ * Fallback on music stream for default initialization to take benefit of property based default
+ * initialization.
+ * For other volume groups not linked to any streams, default music stream index is considered.
+ */
private void updateDefaultVolumes() {
for (int stream = 0; stream < mStreamStates.length; stream++) {
- if (stream != mStreamVolumeAlias[stream]) {
- AudioSystem.DEFAULT_STREAM_VOLUME[stream] = (rescaleIndex(
- AudioSystem.DEFAULT_STREAM_VOLUME[mStreamVolumeAlias[stream]] * 10,
- mStreamVolumeAlias[stream],
- stream) + 5) / 10;
+ int streamVolumeAlias = mStreamVolumeAlias[stream];
+ if (mUseVolumeGroupAliases) {
+ if (AudioSystem.DEFAULT_STREAM_VOLUME[stream] != UNSET_INDEX) {
+ // Already initialized through default property based mecanism.
+ continue;
+ }
+ streamVolumeAlias = AudioSystem.STREAM_MUSIC;
+ int defaultAliasVolume = getUiDefaultRescaledIndex(streamVolumeAlias, stream);
+ if ((defaultAliasVolume >= MIN_STREAM_VOLUME[stream])
+ && (defaultAliasVolume <= MAX_STREAM_VOLUME[stream])) {
+ AudioSystem.DEFAULT_STREAM_VOLUME[stream] = defaultAliasVolume;
+ continue;
+ }
+ }
+ if (stream != streamVolumeAlias) {
+ AudioSystem.DEFAULT_STREAM_VOLUME[stream] =
+ getUiDefaultRescaledIndex(streamVolumeAlias, stream);
}
}
}
+ private int getUiDefaultRescaledIndex(int srcStream, int dstStream) {
+ return (rescaleIndex(AudioSystem.DEFAULT_STREAM_VOLUME[srcStream] * 10,
+ srcStream, dstStream) + 5) / 10;
+ }
+
private void dumpStreamStates(PrintWriter pw) {
pw.println("\nStream volumes (device: index)");
int numStreamTypes = AudioSystem.getNumStreamTypes();
@@ -1740,6 +1795,9 @@
if (mIsSingleVolume) {
mStreamVolumeAlias = STREAM_VOLUME_ALIAS_TELEVISION;
dtmfStreamAlias = AudioSystem.STREAM_MUSIC;
+ } else if (mUseVolumeGroupAliases) {
+ mStreamVolumeAlias = STREAM_VOLUME_ALIAS_NONE;
+ dtmfStreamAlias = AudioSystem.STREAM_DTMF;
} else {
switch (mPlatformType) {
case AudioSystem.PLATFORM_VOICE:
@@ -2768,7 +2826,7 @@
// If either the client forces allowing ringer modes for this adjustment,
// or the stream type is one that is affected by ringer modes
if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
- (streamTypeAlias == getUiSoundsStreamType())) {
+ (isUiSoundsStreamType(streamTypeAlias))) {
int ringerMode = getRingerModeInternal();
// do not vibrate if already in vibrate mode
if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) {
@@ -3570,7 +3628,7 @@
case Settings.Global.ZEN_MODE_ALARMS:
case Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
return !isStreamMutedByRingerOrZenMode(streamTypeAlias)
- || streamTypeAlias == getUiSoundsStreamType()
+ || isUiSoundsStreamType(streamTypeAlias)
|| (flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0;
}
@@ -3987,9 +4045,26 @@
return (mStreamStates[streamType].getIndex(device) + 5) / 10;
}
- /** @see AudioManager#getUiSoundsStreamType() */
+ /** @see AudioManager#getUiSoundsStreamType()
+ * TODO(b/181140246): when using VolumeGroup alias, we are lacking configurability for
+ * UI Sounds identification.
+ * Fallback on Voice configuration to ensure correct behavior of DnD feature.
+ */
public int getUiSoundsStreamType() {
- return mStreamVolumeAlias[AudioSystem.STREAM_SYSTEM];
+ return mUseVolumeGroupAliases ? STREAM_VOLUME_ALIAS_VOICE[AudioSystem.STREAM_SYSTEM]
+ : mStreamVolumeAlias[AudioSystem.STREAM_SYSTEM];
+ }
+
+ /**
+ * TODO(b/181140246): when using VolumeGroup alias, we are lacking configurability for
+ * UI Sounds identification.
+ * Fallback on Voice configuration to ensure correct behavior of DnD feature.
+ */
+ private boolean isUiSoundsStreamType(int aliasStreamType) {
+ return mUseVolumeGroupAliases
+ ? STREAM_VOLUME_ALIAS_VOICE[aliasStreamType]
+ == STREAM_VOLUME_ALIAS_VOICE[AudioSystem.STREAM_SYSTEM]
+ : aliasStreamType == mStreamVolumeAlias[AudioSystem.STREAM_SYSTEM];
}
/** @see AudioManager#setMicrophoneMute(boolean) */
diff --git a/services/core/java/com/android/server/audio/FadeOutManager.java b/services/core/java/com/android/server/audio/FadeOutManager.java
index e08bd67..bb627e5 100644
--- a/services/core/java/com/android/server/audio/FadeOutManager.java
+++ b/services/core/java/com/android/server/audio/FadeOutManager.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.media.AudioAttributes;
+import android.media.AudioManager;
import android.media.AudioPlaybackConfiguration;
import android.media.VolumeShaper;
import android.util.Log;
@@ -35,15 +36,15 @@
public static final String TAG = "AudioService.FadeOutManager";
- /*package*/ static final long FADE_OUT_DURATION_MS = 2500;
+ /*package*/ static final long FADE_OUT_DURATION_MS = 2000;
private static final boolean DEBUG = PlaybackActivityMonitor.DEBUG;
private static final VolumeShaper.Configuration FADEOUT_VSHAPE =
new VolumeShaper.Configuration.Builder()
.setId(PlaybackActivityMonitor.VOLUME_SHAPER_SYSTEM_FADEOUT_ID)
- .setCurve(new float[]{0.f, 1.0f} /* times */,
- new float[]{1.f, 0.0f} /* volumes */)
+ .setCurve(new float[]{0.f, 0.25f, 1.0f} /* times */,
+ new float[]{1.f, 0.65f, 0.0f} /* volumes */)
.setOptionFlags(VolumeShaper.Configuration.OPTION_FLAG_CLOCK_TIME)
.setDuration(FADE_OUT_DURATION_MS)
.build();
@@ -70,6 +71,30 @@
private static final VolumeShaper.Operation PLAY_SKIP_RAMP =
new VolumeShaper.Operation.Builder(PLAY_CREATE_IF_NEEDED).setXOffset(1.0f).build();
+
+ // TODO explore whether a shorter fade out would be a better UX instead of not fading out at all
+ // (legacy behavior)
+ /**
+ * Determine whether the focus request would trigger a fade out, given the parameters of the
+ * requester and those of the focus loser
+ * @param requester the parameters for the focus request
+ * @return true if there can be a fade out over the requester starting to play
+ */
+ static boolean canCauseFadeOut(@NonNull FocusRequester requester,
+ @NonNull FocusRequester loser) {
+ if (requester.getAudioAttributes().getContentType() == AudioAttributes.CONTENT_TYPE_SPEECH)
+ {
+ if (DEBUG) { Log.i(TAG, "not fading out: new focus is for speech"); }
+ return false;
+ }
+ if ((loser.getGrantFlags() & AudioManager.AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS) != 0) {
+ if (DEBUG) { Log.i(TAG, "not fading out: loser has PAUSES_ON_DUCKABLE_LOSS"); }
+ return false;
+ }
+
+ return true;
+ }
+
/**
* Evaluates whether the player associated with this configuration can and should be faded out
* @param apc the configuration of the player
diff --git a/services/core/java/com/android/server/audio/FocusRequester.java b/services/core/java/com/android/server/audio/FocusRequester.java
index cc60fe1..ab8b795 100644
--- a/services/core/java/com/android/server/audio/FocusRequester.java
+++ b/services/core/java/com/android/server/audio/FocusRequester.java
@@ -182,7 +182,7 @@
return mGrantFlags;
}
- AudioAttributes getAudioAttributes() {
+ @NonNull AudioAttributes getAudioAttributes() {
return mAttributes;
}
diff --git a/services/core/java/com/android/server/audio/MediaFocusControl.java b/services/core/java/com/android/server/audio/MediaFocusControl.java
index 0310215..e6c4abfa 100644
--- a/services/core/java/com/android/server/audio/MediaFocusControl.java
+++ b/services/core/java/com/android/server/audio/MediaFocusControl.java
@@ -888,6 +888,7 @@
mEventLogger.log((new AudioEventLogger.StringEvent(
"requestAudioFocus() from uid/pid " + uid
+ "/" + Binder.getCallingPid()
+ + " AA=" + aa.usageToString() + "/" + aa.contentTypeToString()
+ " clientId=" + clientId + " callingPack=" + callingPackageName
+ " req=" + focusChangeHint
+ " flags=0x" + Integer.toHexString(flags)
diff --git a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
index e71219f..af9a14e 100644
--- a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
+++ b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
@@ -707,6 +707,9 @@
if (DEBUG) { Log.v(TAG, "no players to fade out"); }
return false;
}
+ if (!FadeOutManager.canCauseFadeOut(winner, loser)) {
+ return false;
+ }
// check if this UID needs to be faded out (return false if not), and gather list of
// eligible players to fade out
final Iterator<AudioPlaybackConfiguration> apcIterator = mPlayers.values().iterator();
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 d04c17c..2ab1285 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
@@ -68,7 +68,7 @@
private final int[] mKeyguardIgnoreList;
private final int[] mKeyguardIgnoreListVendor;
- private int mLastAcquire;
+ @FaceManager.FaceAcquired private int mLastAcquire = FaceManager.FACE_ACQUIRED_UNKNOWN;
FaceAuthenticationClient(@NonNull Context context,
@NonNull LazyDaemon<ISession> lazyDaemon, @NonNull IBinder token,
@@ -127,7 +127,8 @@
// Do not provide haptic feedback if the user was not detected, and an error (usually
// ERROR_TIMEOUT) is received.
return mLastAcquire != FaceManager.FACE_ACQUIRED_NOT_DETECTED
- && mLastAcquire != FaceManager.FACE_ACQUIRED_SENSOR_DIRTY;
+ && mLastAcquire != FaceManager.FACE_ACQUIRED_SENSOR_DIRTY
+ && mLastAcquire != FaceManager.FACE_ACQUIRED_UNKNOWN;
}
@Override
diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java
index ab67b13..093ecd5 100644
--- a/services/core/java/com/android/server/clipboard/ClipboardService.java
+++ b/services/core/java/com/android/server/clipboard/ClipboardService.java
@@ -379,7 +379,15 @@
return null;
}
synchronized (mLock) {
- addActiveOwnerLocked(intendingUid, pkg);
+ try {
+ addActiveOwnerLocked(intendingUid, pkg);
+ } catch (SecurityException e) {
+ // Permission could not be granted - URI may be invalid
+ Slog.i(TAG, "Could not grant permission to primary clip. Clearing clipboard.");
+ setPrimaryClipInternalLocked(null, intendingUid, pkg);
+ return null;
+ }
+
PerUserClipboard clipboard = getClipboardLocked(intendingUserId);
showAccessNotificationLocked(pkg, intendingUid, intendingUserId, clipboard);
notifyTextClassifierLocked(clipboard, pkg, intendingUid);
diff --git a/services/core/java/com/android/server/display/ColorFade.java b/services/core/java/com/android/server/display/ColorFade.java
index 40ab108..7cb2921 100644
--- a/services/core/java/com/android/server/display/ColorFade.java
+++ b/services/core/java/com/android/server/display/ColorFade.java
@@ -93,6 +93,7 @@
private int mDisplayHeight; // real height, not rotated
private SurfaceControl mSurfaceControl;
private Surface mSurface;
+ private SurfaceControl mBLASTSurfaceControl;
private BLASTBufferQueue mBLASTBufferQueue;
private NaturalSurfaceLayout mSurfaceLayout;
private EGLDisplay mEglDisplay;
@@ -576,7 +577,7 @@
if (mMode == MODE_FADE) {
builder.setColorLayer();
} else {
- builder.setBLASTLayer();
+ builder.setContainerLayer();
}
mSurfaceControl = builder.build();
} catch (OutOfResourcesException ex) {
@@ -592,7 +593,14 @@
mTransaction.apply();
if (mMode != MODE_FADE) {
- mBLASTBufferQueue = new BLASTBufferQueue("ColorFade", mSurfaceControl,
+ final SurfaceControl.Builder b = new SurfaceControl.Builder()
+ .setName("ColorFade BLAST")
+ .setParent(mSurfaceControl)
+ .setHidden(false)
+ .setSecure(isSecure)
+ .setBLASTLayer();
+ mBLASTSurfaceControl = b.build();
+ mBLASTBufferQueue = new BLASTBufferQueue("ColorFade", mBLASTSurfaceControl,
mDisplayWidth, mDisplayHeight, PixelFormat.TRANSLUCENT);
mSurface = mBLASTBufferQueue.createSurface();
}
@@ -723,10 +731,16 @@
mTransaction.remove(mSurfaceControl).apply();
if (mSurface != null) {
mSurface.release();
- mBLASTBufferQueue.destroy();
mSurface = null;
+ }
+
+ if (mBLASTSurfaceControl != null) {
+ mBLASTSurfaceControl.release();
+ mBLASTSurfaceControl = null;
+ mBLASTBufferQueue.destroy();
mBLASTBufferQueue = null;
}
+
mSurfaceControl = null;
mSurfaceVisible = false;
mSurfaceAlpha = 0f;
diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
index 314955b..170564d 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
@@ -422,7 +422,7 @@
if (configBrightnessDefault != null) {
mBrightnessDefault = configBrightnessDefault.floatValue();
} else {
- mBrightnessDefault = BRIGHTNESS_DEFAULT;
+ loadBrightnessDefaultFromConfigXml();
}
}
}
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 4ad8797..52b05f2 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -1362,6 +1362,9 @@
+ mBrightnessReasonTemp.toString(brightnessAdjustmentFlags)
+ "', previous reason: '" + mBrightnessReason + "'.");
mBrightnessReason.set(mBrightnessReasonTemp);
+ } else if (mBrightnessReasonTemp.reason == BrightnessReason.REASON_MANUAL
+ && userSetBrightnessChanged) {
+ Slog.v(TAG, "Brightness [" + brightnessState + "] manual adjustment.");
}
// Update display white-balance.
@@ -2021,7 +2024,8 @@
|| mPendingScreenBrightnessSetting < 0.0f)) {
return false;
}
- if (mCurrentScreenBrightnessSetting == mPendingScreenBrightnessSetting) {
+ if (BrightnessSynchronizer.floatEquals(
+ mCurrentScreenBrightnessSetting, mPendingScreenBrightnessSetting)) {
mPendingScreenBrightnessSetting = PowerManager.BRIGHTNESS_INVALID_FLOAT;
mTemporaryScreenBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
return false;
diff --git a/services/core/java/com/android/server/graphics/fonts/FontManagerService.java b/services/core/java/com/android/server/graphics/fonts/FontManagerService.java
index 0949ddd..ae9c64b4 100644
--- a/services/core/java/com/android/server/graphics/fonts/FontManagerService.java
+++ b/services/core/java/com/android/server/graphics/fonts/FontManagerService.java
@@ -19,26 +19,21 @@
import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
import android.graphics.Typeface;
-import android.graphics.fonts.Font;
import android.graphics.fonts.FontFamily;
-import android.graphics.fonts.FontFileUtil;
import android.graphics.fonts.FontManager;
import android.graphics.fonts.FontUpdateRequest;
import android.graphics.fonts.SystemFonts;
+import android.os.ParcelFileDescriptor;
import android.os.ResultReceiver;
import android.os.SharedMemory;
import android.os.ShellCallback;
import android.system.ErrnoException;
import android.text.FontConfig;
-import android.text.Layout;
-import android.text.StaticLayout;
-import android.text.TextPaint;
-import android.text.TextUtils;
import android.util.AndroidException;
+import android.util.ArrayMap;
import android.util.IndentingPrintWriter;
import android.util.Slog;
@@ -52,24 +47,24 @@
import java.io.File;
import java.io.FileDescriptor;
-import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.ByteBuffer;
+import java.nio.DirectByteBuffer;
import java.nio.NioUtils;
-import java.nio.channels.FileChannel;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/** A service for managing system fonts. */
-// TODO(b/173619554): Add API to update fonts.
public final class FontManagerService extends IFontManager.Stub {
private static final String TAG = "FontManagerService";
private static final String FONT_FILES_DIR = "/data/fonts/files";
+ private static final String CONFIG_XML_FILE = "/data/fonts/config/config.xml";
+ @RequiresPermission(Manifest.permission.UPDATE_FONTS)
@Override
public FontConfig getFontConfig() {
getContext().enforceCallingPermission(Manifest.permission.UPDATE_FONTS,
@@ -77,35 +72,39 @@
return getSystemFontConfig();
}
+ @RequiresPermission(Manifest.permission.UPDATE_FONTS)
@Override
- public int updateFontFile(@NonNull FontUpdateRequest request, int baseVersion) {
- Preconditions.checkArgumentNonnegative(baseVersion);
- Objects.requireNonNull(request);
- Objects.requireNonNull(request.getFd());
- Objects.requireNonNull(request.getSignature());
- getContext().enforceCallingPermission(Manifest.permission.UPDATE_FONTS,
- "UPDATE_FONTS permission required.");
+ public int updateFontFamily(@NonNull List<FontUpdateRequest> requests, int baseVersion) {
try {
- update(baseVersion, Collections.singletonList(request));
- return FontManager.RESULT_SUCCESS;
- } catch (SystemFontException e) {
- Slog.e(TAG, "Failed to update font file", e);
- return e.getErrorCode();
+ Preconditions.checkArgumentNonnegative(baseVersion);
+ Objects.requireNonNull(requests);
+ getContext().enforceCallingPermission(Manifest.permission.UPDATE_FONTS,
+ "UPDATE_FONTS permission required.");
+ try {
+ update(baseVersion, requests);
+ return FontManager.RESULT_SUCCESS;
+ } catch (SystemFontException e) {
+ Slog.e(TAG, "Failed to update font family", e);
+ return e.getErrorCode();
+ }
+ } finally {
+ closeFileDescriptors(requests);
}
}
- @Override
- public int updateFontFamily(@NonNull List<FontUpdateRequest> requests, int baseVersion) {
- Preconditions.checkArgumentNonnegative(baseVersion);
- Objects.requireNonNull(requests);
- getContext().enforceCallingPermission(Manifest.permission.UPDATE_FONTS,
- "UPDATE_FONTS permission required.");
- try {
- update(baseVersion, requests);
- return FontManager.RESULT_SUCCESS;
- } catch (SystemFontException e) {
- Slog.e(TAG, "Failed to update font family", e);
- return e.getErrorCode();
+ private static void closeFileDescriptors(@Nullable List<FontUpdateRequest> requests) {
+ // Make sure we close every passed FD, even if 'requests' is constructed incorrectly and
+ // some fields are null.
+ if (requests == null) return;
+ for (FontUpdateRequest request : requests) {
+ if (request == null) continue;
+ ParcelFileDescriptor fd = request.getFd();
+ if (fd == null) continue;
+ try {
+ fd.close();
+ } catch (IOException e) {
+ Slog.w(TAG, "Failed to close fd", e);
+ }
}
}
@@ -132,9 +131,9 @@
public static final class Lifecycle extends SystemService {
private final FontManagerService mService;
- public Lifecycle(@NonNull Context context) {
+ public Lifecycle(@NonNull Context context, boolean safeMode) {
super(context);
- mService = new FontManagerService(context);
+ mService = new FontManagerService(context, safeMode);
}
@Override
@@ -154,89 +153,6 @@
}
}
- /* package */ static class OtfFontFileParser implements UpdatableFontDir.FontFileParser {
- @Override
- public String getPostScriptName(File file) throws IOException {
- ByteBuffer buffer = mmap(file);
- try {
- return FontFileUtil.getPostScriptName(buffer, 0);
- } finally {
- NioUtils.freeDirectBuffer(buffer);
- }
- }
-
- @Override
- public String buildFontFileName(File file) throws IOException {
- ByteBuffer buffer = mmap(file);
- try {
- String psName = FontFileUtil.getPostScriptName(buffer, 0);
- int isType1Font = FontFileUtil.isPostScriptType1Font(buffer, 0);
- int isCollection = FontFileUtil.isCollectionFont(buffer);
-
- if (TextUtils.isEmpty(psName) || isType1Font == -1 || isCollection == -1) {
- return null;
- }
-
- String extension;
- if (isCollection == 1) {
- extension = isType1Font == 1 ? ".otc" : ".ttc";
- } else {
- extension = isType1Font == 1 ? ".otf" : ".ttf";
- }
- return psName + extension;
- } finally {
- NioUtils.freeDirectBuffer(buffer);
- }
-
- }
-
- @Override
- public long getRevision(File file) throws IOException {
- ByteBuffer buffer = mmap(file);
- try {
- return FontFileUtil.getRevision(buffer, 0);
- } finally {
- NioUtils.freeDirectBuffer(buffer);
- }
- }
-
- @Override
- public void tryToCreateTypeface(File file) throws Throwable {
- Font font = new Font.Builder(file).build();
- FontFamily family = new FontFamily.Builder(font).build();
- Typeface typeface = new Typeface.CustomFallbackBuilder(family).build();
-
- TextPaint p = new TextPaint();
- p.setTextSize(24f);
- p.setTypeface(typeface);
-
- // Test string to try with the passed font.
- // TODO: Good to extract from font file.
- String testTextToDraw = "abcXYZ@- "
- + "\uD83E\uDED6" // Emoji E13.0
- + "\uD83C\uDDFA\uD83C\uDDF8" // Emoji Flags
- + "\uD83D\uDC8F\uD83C\uDFFB" // Emoji Skin tone Sequence
- // ZWJ Sequence
- + "\uD83D\uDC68\uD83C\uDFFC\u200D\u2764\uFE0F\u200D\uD83D\uDC8B\u200D"
- + "\uD83D\uDC68\uD83C\uDFFF";
-
- int width = (int) Math.ceil(Layout.getDesiredWidth(testTextToDraw, p));
- StaticLayout layout = StaticLayout.Builder.obtain(
- testTextToDraw, 0, testTextToDraw.length(), p, width).build();
- Bitmap bmp = Bitmap.createBitmap(
- layout.getWidth(), layout.getHeight(), Bitmap.Config.ALPHA_8);
- Canvas canvas = new Canvas(bmp);
- layout.draw(canvas);
- }
-
- private static ByteBuffer mmap(File file) throws IOException {
- try (FileInputStream in = new FileInputStream(file)) {
- FileChannel fileChannel = in.getChannel();
- return fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, fileChannel.size());
- }
- }
- }
-
private static class FsverityUtilImpl implements UpdatableFontDir.FsverityUtil {
@Override
public boolean hasFsverity(String filePath) {
@@ -272,30 +188,30 @@
@Nullable
private SharedMemory mSerializedFontMap = null;
- private FontManagerService(Context context) {
+ private FontManagerService(Context context, boolean safeMode) {
+ if (safeMode) {
+ Slog.i(TAG, "Entering safe mode. Deleting all font updates.");
+ UpdatableFontDir.deleteAllFiles(new File(FONT_FILES_DIR), new File(CONFIG_XML_FILE));
+ }
mContext = context;
- mUpdatableFontDir = createUpdatableFontDir();
+ mUpdatableFontDir = createUpdatableFontDir(safeMode);
initialize();
}
@Nullable
- private static UpdatableFontDir createUpdatableFontDir() {
+ private static UpdatableFontDir createUpdatableFontDir(boolean safeMode) {
+ // Never read updatable font files in safe mode.
+ if (safeMode) return null;
// If apk verity is supported, fs-verity should be available.
if (!VerityUtils.isFsVeritySupported()) return null;
- return new UpdatableFontDir(new File(FONT_FILES_DIR),
- new OtfFontFileParser(), new FsverityUtilImpl());
+ return new UpdatableFontDir(new File(FONT_FILES_DIR), new OtfFontFileParser(),
+ new FsverityUtilImpl(), new File(CONFIG_XML_FILE));
}
private void initialize() {
synchronized (mUpdatableFontDirLock) {
if (mUpdatableFontDir == null) {
- synchronized (mSerializedFontMapLock) {
- try {
- mSerializedFontMap = Typeface.serializeFontMap(Typeface.getSystemFontMap());
- } catch (IOException | ErrnoException e) {
- mSerializedFontMap = null;
- }
- }
+ setSerializedFontMap(serializeSystemServerFontMap());
return;
}
mUpdatableFontDir.loadFontFileMap();
@@ -334,18 +250,23 @@
}
}
- /* package */ void clearUpdates() throws SystemFontException {
- if (mUpdatableFontDir == null) {
- throw new SystemFontException(
- FontManager.RESULT_ERROR_FONT_UPDATER_DISABLED,
- "The font updater is disabled.");
- }
- synchronized (mUpdatableFontDirLock) {
- mUpdatableFontDir.clearUpdates();
- updateSerializedFontMap();
- }
+ /**
+ * Clears all updates and restarts FontManagerService.
+ *
+ * <p>CAUTION: this method is not safe. Existing processes may crash due to missing font files.
+ * This method is only for {@link FontManagerShellCommand}.
+ */
+ /* package */ void clearUpdates() {
+ UpdatableFontDir.deleteAllFiles(new File(FONT_FILES_DIR), new File(CONFIG_XML_FILE));
+ initialize();
}
+ /**
+ * Restarts FontManagerService, removing not-the-latest font files.
+ *
+ * <p>CAUTION: this method is not safe. Existing processes may crash due to missing font files.
+ * This method is only for {@link FontManagerShellCommand}.
+ */
/* package */ void restart() {
initialize();
}
@@ -391,36 +312,57 @@
/**
* Makes new serialized font map data and updates mSerializedFontMap.
*/
- public void updateSerializedFontMap() {
+ private void updateSerializedFontMap() {
+ SharedMemory serializedFontMap = serializeFontMap(getSystemFontConfig());
+ if (serializedFontMap == null) {
+ // Fallback to the preloaded config.
+ serializedFontMap = serializeSystemServerFontMap();
+ }
+ setSerializedFontMap(serializedFontMap);
+ }
+
+ @Nullable
+ private static SharedMemory serializeFontMap(FontConfig fontConfig) {
+ final ArrayMap<String, ByteBuffer> bufferCache = new ArrayMap<>();
try {
- final FontConfig fontConfig = getSystemFontConfig();
- final Map<String, FontFamily[]> fallback = SystemFonts.buildSystemFallback(fontConfig);
+ final Map<String, FontFamily[]> fallback =
+ SystemFonts.buildSystemFallback(fontConfig, bufferCache);
final Map<String, Typeface> typefaceMap =
SystemFonts.buildSystemTypefaces(fontConfig, fallback);
-
- SharedMemory serializeFontMap = Typeface.serializeFontMap(typefaceMap);
- synchronized (mSerializedFontMapLock) {
- mSerializedFontMap = serializeFontMap;
- }
- return;
+ return Typeface.serializeFontMap(typefaceMap);
} catch (IOException | ErrnoException e) {
Slog.w(TAG, "Failed to serialize updatable font map. "
+ "Retrying with system image fonts.", e);
- }
-
- try {
- final FontConfig fontConfig = SystemFonts.getSystemPreinstalledFontConfig();
- final Map<String, FontFamily[]> fallback = SystemFonts.buildSystemFallback(fontConfig);
- final Map<String, Typeface> typefaceMap =
- SystemFonts.buildSystemTypefaces(fontConfig, fallback);
-
- SharedMemory serializeFontMap = Typeface.serializeFontMap(typefaceMap);
- synchronized (mSerializedFontMapLock) {
- mSerializedFontMap = serializeFontMap;
+ return null;
+ } finally {
+ // Unmap buffers promptly, as we map a lot of files and may hit mmap limit before
+ // GC collects ByteBuffers and unmaps them.
+ for (ByteBuffer buffer : bufferCache.values()) {
+ if (buffer instanceof DirectByteBuffer) {
+ NioUtils.freeDirectBuffer(buffer);
+ }
}
- } catch (IOException | ErrnoException e) {
- Slog.e(TAG, "Failed to serialize SystemServer system font map", e);
}
}
+ @Nullable
+ private static SharedMemory serializeSystemServerFontMap() {
+ try {
+ return Typeface.serializeFontMap(Typeface.getSystemFontMap());
+ } catch (IOException | ErrnoException e) {
+ Slog.e(TAG, "Failed to serialize SystemServer system font map", e);
+ return null;
+ }
+ }
+
+ private void setSerializedFontMap(SharedMemory serializedFontMap) {
+ SharedMemory oldFontMap = null;
+ synchronized (mSerializedFontMapLock) {
+ oldFontMap = mSerializedFontMap;
+ mSerializedFontMap = serializedFontMap;
+ }
+ if (oldFontMap != null) {
+ oldFontMap.close();
+ }
+ }
}
diff --git a/services/core/java/com/android/server/graphics/fonts/FontManagerShellCommand.java b/services/core/java/com/android/server/graphics/fonts/FontManagerShellCommand.java
index e4928ce..3fecef7 100644
--- a/services/core/java/com/android/server/graphics/fonts/FontManagerShellCommand.java
+++ b/services/core/java/com/android/server/graphics/fonts/FontManagerShellCommand.java
@@ -448,7 +448,7 @@
}
}
- private int clear(ShellCommand shell) throws SystemFontException {
+ private int clear(ShellCommand shell) {
mService.clearUpdates();
shell.getOutPrintWriter().println("Success");
return 0;
diff --git a/services/core/java/com/android/server/graphics/fonts/OtfFontFileParser.java b/services/core/java/com/android/server/graphics/fonts/OtfFontFileParser.java
new file mode 100644
index 0000000..1ed3972
--- /dev/null
+++ b/services/core/java/com/android/server/graphics/fonts/OtfFontFileParser.java
@@ -0,0 +1,130 @@
+/*
+ * 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.graphics.fonts;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Typeface;
+import android.graphics.fonts.Font;
+import android.graphics.fonts.FontFamily;
+import android.graphics.fonts.FontFileUtil;
+import android.text.Layout;
+import android.text.StaticLayout;
+import android.text.TextPaint;
+import android.text.TextUtils;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.DirectByteBuffer;
+import java.nio.NioUtils;
+import java.nio.channels.FileChannel;
+
+/* package */ class OtfFontFileParser implements UpdatableFontDir.FontFileParser {
+ @Override
+ public String getPostScriptName(File file) throws IOException {
+ ByteBuffer buffer = mmap(file);
+ try {
+ return FontFileUtil.getPostScriptName(buffer, 0);
+ } finally {
+ unmap(buffer);
+ }
+ }
+
+ @Override
+ public String buildFontFileName(File file) throws IOException {
+ ByteBuffer buffer = mmap(file);
+ try {
+ String psName = FontFileUtil.getPostScriptName(buffer, 0);
+ int isType1Font = FontFileUtil.isPostScriptType1Font(buffer, 0);
+ int isCollection = FontFileUtil.isCollectionFont(buffer);
+
+ if (TextUtils.isEmpty(psName) || isType1Font == -1 || isCollection == -1) {
+ return null;
+ }
+
+ String extension;
+ if (isCollection == 1) {
+ extension = isType1Font == 1 ? ".otc" : ".ttc";
+ } else {
+ extension = isType1Font == 1 ? ".otf" : ".ttf";
+ }
+ return psName + extension;
+ } finally {
+ unmap(buffer);
+ }
+
+ }
+
+ @Override
+ public long getRevision(File file) throws IOException {
+ ByteBuffer buffer = mmap(file);
+ try {
+ return FontFileUtil.getRevision(buffer, 0);
+ } finally {
+ unmap(buffer);
+ }
+ }
+
+ @Override
+ public void tryToCreateTypeface(File file) throws Throwable {
+ ByteBuffer buffer = mmap(file);
+ try {
+ Font font = new Font.Builder(buffer).build();
+ FontFamily family = new FontFamily.Builder(font).build();
+ Typeface typeface = new Typeface.CustomFallbackBuilder(family).build();
+
+ TextPaint p = new TextPaint();
+ p.setTextSize(24f);
+ p.setTypeface(typeface);
+
+ // Test string to try with the passed font.
+ // TODO: Good to extract from font file.
+ String testTextToDraw = "abcXYZ@- "
+ + "\uD83E\uDED6" // Emoji E13.0
+ + "\uD83C\uDDFA\uD83C\uDDF8" // Emoji Flags
+ + "\uD83D\uDC8F\uD83C\uDFFB" // Emoji Skin tone Sequence
+ // ZWJ Sequence
+ + "\uD83D\uDC68\uD83C\uDFFC\u200D\u2764\uFE0F\u200D\uD83D\uDC8B\u200D"
+ + "\uD83D\uDC68\uD83C\uDFFF";
+
+ int width = (int) Math.ceil(Layout.getDesiredWidth(testTextToDraw, p));
+ StaticLayout layout = StaticLayout.Builder.obtain(
+ testTextToDraw, 0, testTextToDraw.length(), p, width).build();
+ Bitmap bmp = Bitmap.createBitmap(
+ layout.getWidth(), layout.getHeight(), Bitmap.Config.ALPHA_8);
+ Canvas canvas = new Canvas(bmp);
+ layout.draw(canvas);
+ } finally {
+ unmap(buffer);
+ }
+ }
+
+ private static ByteBuffer mmap(File file) throws IOException {
+ try (FileInputStream in = new FileInputStream(file)) {
+ FileChannel fileChannel = in.getChannel();
+ return fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, fileChannel.size());
+ }
+ }
+
+ private static void unmap(ByteBuffer buffer) {
+ if (buffer instanceof DirectByteBuffer) {
+ NioUtils.freeDirectBuffer(buffer);
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java b/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java
index 981cc838..743b4d9 100644
--- a/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java
+++ b/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java
@@ -59,8 +59,6 @@
private static final String TAG = "UpdatableFontDir";
private static final String RANDOM_DIR_PREFIX = "~~";
- private static final String CONFIG_XML_FILE = "/data/fonts/config/config.xml";
-
/** Interface to mock font file access in tests. */
interface FontFileParser {
String getPostScriptName(File file) throws IOException;
@@ -139,8 +137,9 @@
*/
private final ArrayMap<String, FontFileInfo> mFontFileInfoMap = new ArrayMap<>();
- UpdatableFontDir(File filesDir, FontFileParser parser, FsverityUtil fsverityUtil) {
- this(filesDir, parser, fsverityUtil, new File(CONFIG_XML_FILE),
+ UpdatableFontDir(File filesDir, FontFileParser parser, FsverityUtil fsverityUtil,
+ File configFile) {
+ this(filesDir, parser, fsverityUtil, configFile,
System::currentTimeMillis,
(map) -> SystemFonts.getSystemFontConfig(map, 0, 0)
);
@@ -215,17 +214,6 @@
}
}
- /* package */ void clearUpdates() throws SystemFontException {
- mFontFileInfoMap.clear();
- FileUtils.deleteContents(mFilesDir);
-
- mLastModifiedMillis = mCurrentTimeSupplier.get();
- PersistentSystemFontConfig.Config config = new PersistentSystemFontConfig.Config();
- config.lastModifiedMillis = mLastModifiedMillis;
- writePersistentConfig(config);
- mConfigVersion++;
- }
-
/**
* Applies multiple {@link FontUpdateRequest}s in transaction.
* If one of the request fails, the fonts and config are rolled back to the previous state
@@ -616,4 +604,19 @@
}
return familyMap;
}
+
+ /* package */ static void deleteAllFiles(File filesDir, File configFile) {
+ // As this method is called in safe mode, try to delete all files even though an exception
+ // is thrown.
+ try {
+ new AtomicFile(configFile).delete();
+ } catch (Throwable t) {
+ Slog.w(TAG, "Failed to delete " + configFile);
+ }
+ try {
+ FileUtils.deleteContents(filesDir);
+ } catch (Throwable t) {
+ Slog.w(TAG, "Failed to delete " + filesDir);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
index dcd0eb8..37ee76b 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
@@ -262,18 +262,6 @@
return super.handleUserControlPressed(message);
}
- @Override
- protected void wakeUpIfActiveSource() {
- if (!isActiveSource()) {
- return;
- }
- // Wake up the device if the power is in standby mode, or its screen is off -
- // which can happen if the device is holding a partial lock.
- if (mService.isPowerStandbyOrTransient() || !mService.getPowerManager().isScreenOn()) {
- mService.wakeUp();
- }
- }
-
@ServiceThreadOnly
@Constants.HandleMessageResult
protected int handleSetMenuLanguage(HdmiCecMessage message) {
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceSource.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceSource.java
index 702f854..1c726e0 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceSource.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceSource.java
@@ -380,7 +380,7 @@
if (!isActiveSource()) {
return;
}
- // Wake up the device
+ // Wake up the device. This will also exit dream mode.
mService.wakeUp();
return;
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 77de187..2ed160a 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -442,18 +442,85 @@
public HdmiControlService(Context context) {
super(context);
- List<Integer> deviceTypes = HdmiProperties.device_type();
- if (deviceTypes.contains(null)) {
- Slog.w(TAG, "Error parsing ro.hdmi.device.type: " + SystemProperties.get(
- "ro.hdmi.device_type"));
- deviceTypes = deviceTypes.stream().filter(Objects::nonNull).collect(
- Collectors.toList());
- }
- mLocalDevices = deviceTypes;
+ mLocalDevices = readDeviceTypes();
mSettingsObserver = new SettingsObserver(mHandler);
mHdmiCecConfig = new HdmiCecConfig(context);
}
+ @VisibleForTesting
+ protected List<HdmiProperties.cec_device_types_values> getCecDeviceTypes() {
+ return HdmiProperties.cec_device_types();
+ }
+
+ @VisibleForTesting
+ protected List<Integer> getDeviceTypes() {
+ return HdmiProperties.device_type();
+ }
+
+ /**
+ * Extracts a list of integer device types from the sysprop ro.hdmi.cec_device_types.
+ * If ro.hdmi.cec_device_types is not set, reads from ro.hdmi.device.type instead.
+ * @return the list of integer device types
+ */
+ @VisibleForTesting
+ protected List<Integer> readDeviceTypes() {
+ List<HdmiProperties.cec_device_types_values> cecDeviceTypes = getCecDeviceTypes();
+ if (!cecDeviceTypes.isEmpty()) {
+ if (cecDeviceTypes.contains(null)) {
+ Slog.w(TAG, "Error parsing ro.hdmi.cec_device_types: " + SystemProperties.get(
+ "ro.hdmi.cec_device_types"));
+ }
+ return cecDeviceTypes.stream()
+ .map(HdmiControlService::enumToIntDeviceType)
+ .filter(Objects::nonNull)
+ .collect(Collectors.toList());
+ } else {
+ // If ro.hdmi.cec_device_types isn't set, fall back to reading ro.hdmi.device_type
+ List<Integer> deviceTypes = getDeviceTypes();
+ if (deviceTypes.contains(null)) {
+ Slog.w(TAG, "Error parsing ro.hdmi.device_type: " + SystemProperties.get(
+ "ro.hdmi.device_type"));
+ }
+ return deviceTypes.stream()
+ .filter(Objects::nonNull)
+ .collect(Collectors.toList());
+ }
+ }
+
+ /**
+ * Converts an enum representing a value in ro.hdmi.cec_device_types to an integer device type.
+ * Returns null if the input is null or an unrecognized device type.
+ */
+ @Nullable
+ private static Integer enumToIntDeviceType(
+ @Nullable HdmiProperties.cec_device_types_values cecDeviceType) {
+ if (cecDeviceType == null) {
+ return null;
+ }
+ switch (cecDeviceType) {
+ case TV:
+ return HdmiDeviceInfo.DEVICE_TV;
+ case RECORDING_DEVICE:
+ return HdmiDeviceInfo.DEVICE_RECORDER;
+ case RESERVED:
+ return HdmiDeviceInfo.DEVICE_RESERVED;
+ case TUNER:
+ return HdmiDeviceInfo.DEVICE_TUNER;
+ case PLAYBACK_DEVICE:
+ return HdmiDeviceInfo.DEVICE_PLAYBACK;
+ case AUDIO_SYSTEM:
+ return HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM;
+ case PURE_CEC_SWITCH:
+ return HdmiDeviceInfo.DEVICE_PURE_CEC_SWITCH;
+ case VIDEO_PROCESSOR:
+ return HdmiDeviceInfo.DEVICE_VIDEO_PROCESSOR;
+ default:
+ Slog.w(TAG, "Unrecognized device type in ro.hdmi.cec_device_types: "
+ + cecDeviceType.getPropValue());
+ return null;
+ }
+ }
+
protected static List<Integer> getIntList(String string) {
ArrayList<Integer> list = new ArrayList<>();
TextUtils.SimpleStringSplitter splitter = new TextUtils.SimpleStringSplitter(',');
@@ -3030,6 +3097,7 @@
@ServiceThreadOnly
@VisibleForTesting
protected void onStandby(final int standbyAction) {
+ mWakeUpMessageReceived = false;
assertRunOnServiceThread();
mPowerStatusController.setPowerStatus(HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY,
false);
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 518c428..94e669a 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -5761,6 +5761,7 @@
final String imeId = shellCommand.getNextArgRequired();
final PrintWriter out = shellCommand.getOutPrintWriter();
final PrintWriter error = shellCommand.getErrPrintWriter();
+ boolean hasFailed = false;
synchronized (mMethodMap) {
final int[] userIds = InputMethodUtils.resolveUserId(userIdToBeResolved,
mSettings.getCurrentUserId(), shellCommand.getErrPrintWriter());
@@ -5768,11 +5769,11 @@
if (!userHasDebugPriv(userId, shellCommand)) {
continue;
}
- handleShellCommandEnableDisableInputMethodInternalLocked(userId, imeId, enabled,
- out, error);
+ hasFailed |= !handleShellCommandEnableDisableInputMethodInternalLocked(
+ userId, imeId, enabled, out, error);
}
}
- return ShellCommandResult.SUCCESS;
+ return hasFailed ? ShellCommandResult.FAILURE : ShellCommandResult.SUCCESS;
}
/**
@@ -5804,8 +5805,18 @@
return UserHandle.USER_CURRENT;
}
+ /**
+ * Handles core logic of {@code adb shell ime enable} and {@code adb shell ime disable}.
+ *
+ * @param userId user ID specified to the command. Pseudo user IDs are not supported.
+ * @param imeId IME ID specified to the command.
+ * @param enabled {@code true} for {@code adb shell ime enable}. {@code false} otherwise.
+ * @param out {@link PrintWriter} to output standard messages.
+ * @param error {@link PrintWriter} to output error messages.
+ * @return {@code false} if it fails to enable the IME. {@code false} otherwise.
+ */
@BinderThread
- private void handleShellCommandEnableDisableInputMethodInternalLocked(
+ private boolean handleShellCommandEnableDisableInputMethodInternalLocked(
@UserIdInt int userId, String imeId, boolean enabled, PrintWriter out,
PrintWriter error) {
boolean failedToEnableUnknownIme = false;
@@ -5851,15 +5862,20 @@
error.print("Unknown input method ");
error.print(imeId);
error.println(" cannot be enabled for user #" + userId);
- } else {
- out.print("Input method ");
- out.print(imeId);
- out.print(": ");
- out.print((enabled == previouslyEnabled) ? "already " : "now ");
- out.print(enabled ? "enabled" : "disabled");
- out.print(" for user #");
- out.println(userId);
+ // Also print this failure into logcat for better debuggability.
+ Slog.e(TAG, "\"ime enable " + imeId + "\" for user #" + userId
+ + " failed due to its unrecognized IME ID.");
+ return false;
}
+
+ out.print("Input method ");
+ out.print(imeId);
+ out.print(": ");
+ out.print((enabled == previouslyEnabled) ? "already " : "now ");
+ out.print(enabled ? "enabled" : "disabled");
+ out.print(" for user #");
+ out.println(userId);
+ return true;
}
/**
@@ -5874,6 +5890,7 @@
final String imeId = shellCommand.getNextArgRequired();
final PrintWriter out = shellCommand.getOutPrintWriter();
final PrintWriter error = shellCommand.getErrPrintWriter();
+ boolean hasFailed = false;
synchronized (mMethodMap) {
final int[] userIds = InputMethodUtils.resolveUserId(userIdToBeResolved,
mSettings.getCurrentUserId(), shellCommand.getErrPrintWriter());
@@ -5887,15 +5904,19 @@
error.print(imeId);
error.print(" cannot be selected for user #");
error.println(userId);
+ // Also print this failure into logcat for better debuggability.
+ Slog.e(TAG, "\"ime set " + imeId + "\" for user #" + userId
+ + " failed due to its unrecognized IME ID.");
} else {
out.print("Input method ");
out.print(imeId);
out.print(" selected for user #");
out.println(userId);
}
+ hasFailed |= failedToSelectUnknownIme;
}
}
- return ShellCommandResult.SUCCESS;
+ return hasFailed ? ShellCommandResult.FAILURE : ShellCommandResult.SUCCESS;
}
/**
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodSubtypeSwitchingController.java b/services/core/java/com/android/server/inputmethod/InputMethodSubtypeSwitchingController.java
index 2969e53..c340a2b 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodSubtypeSwitchingController.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodSubtypeSwitchingController.java
@@ -196,7 +196,7 @@
final int numImes = imis.size();
for (int i = 0; i < numImes; ++i) {
final InputMethodInfo imi = imis.get(i);
- if (forImeMenu && !imi.showInInputMethodPicker()) {
+ if (forImeMenu && !imi.shouldShowInInputMethodPicker()) {
continue;
}
final List<InputMethodSubtype> explicitlyOrImplicitlyEnabledSubtypeList =
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index 3c14440..4ee867b 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -181,7 +181,7 @@
private static final int MSG_PERFORM_POLL = 1;
// Perform polling, persist network, and register the global alert again.
private static final int MSG_PERFORM_POLL_REGISTER_ALERT = 2;
- private static final int MSG_UPDATE_IFACES = 3;
+ private static final int MSG_NOTIFY_NETWORK_STATUS = 3;
// A message for broadcasting ACTION_NETWORK_STATS_UPDATED in handler thread to prevent
// deadlock.
private static final int MSG_BROADCAST_NETWORK_STATS_UPDATED = 4;
@@ -379,11 +379,12 @@
performPoll(FLAG_PERSIST_ALL);
break;
}
- case MSG_UPDATE_IFACES: {
+ case MSG_NOTIFY_NETWORK_STATUS: {
// If no cached states, ignore.
if (mLastNetworkStateSnapshots == null) break;
// TODO (b/181642673): Protect mDefaultNetworks from concurrent accessing.
- updateIfaces(mDefaultNetworks, mLastNetworkStateSnapshots, mActiveIface);
+ handleNotifyNetworkStatus(
+ mDefaultNetworks, mLastNetworkStateSnapshots, mActiveIface);
break;
}
case MSG_PERFORM_POLL_REGISTER_ALERT: {
@@ -474,7 +475,7 @@
@NonNull Looper looper, @NonNull Executor executor,
@NonNull NetworkStatsService service) {
// TODO: Update RatType passively in NSS, instead of querying into the monitor
- // when forceUpdateIface.
+ // when notifyNetworkStatus.
return new NetworkStatsSubscriptionsMonitor(context, looper, executor,
(subscriberId, type) -> service.handleOnCollapsedRatTypeChanged());
}
@@ -971,16 +972,19 @@
}
}
- public void forceUpdateIfaces(
- Network[] defaultNetworks,
- NetworkStateSnapshot[] networkStates,
- String activeIface,
- UnderlyingNetworkInfo[] underlyingNetworkInfos) {
+ /**
+ * Notify {@code NetworkStatsService} about network status changed.
+ */
+ public void notifyNetworkStatus(
+ @NonNull Network[] defaultNetworks,
+ @NonNull NetworkStateSnapshot[] networkStates,
+ @Nullable String activeIface,
+ @NonNull UnderlyingNetworkInfo[] underlyingNetworkInfos) {
checkNetworkStackPermission(mContext);
final long token = Binder.clearCallingIdentity();
try {
- updateIfaces(defaultNetworks, networkStates, activeIface);
+ handleNotifyNetworkStatus(defaultNetworks, networkStates, activeIface);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -1244,12 +1248,12 @@
@VisibleForTesting
public void handleOnCollapsedRatTypeChanged() {
// Protect service from frequently updating. Remove pending messages if any.
- mHandler.removeMessages(MSG_UPDATE_IFACES);
+ mHandler.removeMessages(MSG_NOTIFY_NETWORK_STATUS);
mHandler.sendMessageDelayed(
- mHandler.obtainMessage(MSG_UPDATE_IFACES), mSettings.getPollDelay());
+ mHandler.obtainMessage(MSG_NOTIFY_NETWORK_STATUS), mSettings.getPollDelay());
}
- private void updateIfaces(
+ private void handleNotifyNetworkStatus(
Network[] defaultNetworks,
NetworkStateSnapshot[] snapshots,
String activeIface) {
@@ -1257,7 +1261,7 @@
mWakeLock.acquire();
try {
mActiveIface = activeIface;
- updateIfacesLocked(defaultNetworks, snapshots);
+ handleNotifyNetworkStatusLocked(defaultNetworks, snapshots);
} finally {
mWakeLock.release();
}
@@ -1270,10 +1274,10 @@
* they are combined under a single {@link NetworkIdentitySet}.
*/
@GuardedBy("mStatsLock")
- private void updateIfacesLocked(@NonNull Network[] defaultNetworks,
+ private void handleNotifyNetworkStatusLocked(@NonNull Network[] defaultNetworks,
@NonNull NetworkStateSnapshot[] snapshots) {
if (!mSystemReady) return;
- if (LOGV) Slog.v(TAG, "updateIfacesLocked()");
+ if (LOGV) Slog.v(TAG, "handleNotifyNetworkStatusLocked()");
// take one last stats snapshot before updating iface mapping. this
// isn't perfect, since the kernel may already be counting traffic from
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 19c717d..0700a9f 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -9984,6 +9984,7 @@
static final String TAG_APPROVED = "allowed";
static final String TAG_DISALLOWED= "disallowed";
static final String XML_SEPARATOR = ",";
+ static final String FLAG_SEPARATOR = "\\|";
private final ArraySet<ManagedServiceInfo> mLightTrimListeners = new ArraySet<>();
ArrayMap<Pair<ComponentName, Integer>, NotificationListenerFilter>
@@ -10255,7 +10256,7 @@
private int getTypesFromStringList(String typeList) {
int types = 0;
if (typeList != null) {
- String[] typeStrings = typeList.split(XML_SEPARATOR);
+ String[] typeStrings = typeList.split(FLAG_SEPARATOR);
for (int i = 0; i < typeStrings.length; i++) {
final String typeString = typeStrings[i];
if (TextUtils.isEmpty(typeString)) {
diff --git a/services/core/java/com/android/server/os/OWNERS b/services/core/java/com/android/server/os/OWNERS
new file mode 100644
index 0000000..1957332
--- /dev/null
+++ b/services/core/java/com/android/server/os/OWNERS
@@ -0,0 +1,2 @@
+# Bugreporting
+per-file Bugreport* = file:/platform/frameworks/native:/cmds/dumpstate/OWNERS
diff --git a/services/core/java/com/android/server/pm/AppsFilter.java b/services/core/java/com/android/server/pm/AppsFilter.java
index cd352b5..7b1fa14 100644
--- a/services/core/java/com/android/server/pm/AppsFilter.java
+++ b/services/core/java/com/android/server/pm/AppsFilter.java
@@ -84,6 +84,7 @@
// Logs all filtering instead of enforcing
private static final boolean DEBUG_ALLOW_ALL = false;
private static final boolean DEBUG_LOGGING = false;
+ private static final boolean DEBUG_TRACING = false;
/**
* This contains a list of app UIDs that are implicitly queryable because another app explicitly
@@ -363,21 +364,29 @@
@Override
public boolean isGloballyEnabled() {
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "isGloballyEnabled");
+ if (DEBUG_TRACING) {
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "isGloballyEnabled");
+ }
try {
return mFeatureEnabled;
} finally {
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ if (DEBUG_TRACING) {
+ Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ }
}
}
@Override
public boolean packageIsEnabled(AndroidPackage pkg) {
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "packageIsEnabled");
+ if (DEBUG_TRACING) {
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "packageIsEnabled");
+ }
try {
return !mDisabledPackages.contains(pkg.getPackageName());
} finally {
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ if (DEBUG_TRACING) {
+ Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ }
}
}
@@ -656,7 +665,9 @@
* @param isReplace if the package is being replaced and may need extra cleanup.
*/
public void addPackage(PackageSetting newPkgSetting, boolean isReplace) {
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "filter.addPackage");
+ if (DEBUG_TRACING) {
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "filter.addPackage");
+ }
try {
if (isReplace) {
// let's first remove any prior rules for this package
@@ -689,7 +700,9 @@
});
} finally {
onChanged();
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ if (DEBUG_TRACING) {
+ Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ }
}
}
@@ -1173,7 +1186,9 @@
*/
public boolean shouldFilterApplication(int callingUid, @Nullable SettingBase callingSetting,
PackageSetting targetPkgSetting, int userId) {
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "shouldFilterApplication");
+ if (DEBUG_TRACING) {
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "shouldFilterApplication");
+ }
try {
int callingAppId = UserHandle.getAppId(callingUid);
if (callingAppId < Process.FIRST_APPLICATION_UID
@@ -1211,13 +1226,17 @@
}
return !DEBUG_ALLOW_ALL;
} finally {
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ if (DEBUG_TRACING) {
+ Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ }
}
}
private boolean shouldFilterApplicationInternal(int callingUid, SettingBase callingSetting,
PackageSetting targetPkgSetting, int targetUserId) {
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "shouldFilterApplicationInternal");
+ if (DEBUG_TRACING) {
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "shouldFilterApplicationInternal");
+ }
try {
final boolean featureEnabled = mFeatureConfig.isGloballyEnabled();
if (!featureEnabled) {
@@ -1232,7 +1251,9 @@
}
final PackageSetting callingPkgSetting;
final ArraySet<PackageSetting> callingSharedPkgSettings;
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "callingSetting instanceof");
+ if (DEBUG_TRACING) {
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "callingSetting instanceof");
+ }
if (callingSetting instanceof PackageSetting) {
if (((PackageSetting) callingSetting).sharedUser == null) {
callingPkgSetting = (PackageSetting) callingSetting;
@@ -1246,7 +1267,9 @@
callingPkgSetting = null;
callingSharedPkgSettings = ((SharedUserSetting) callingSetting).packages;
}
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ if (DEBUG_TRACING) {
+ Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ }
if (callingPkgSetting != null) {
if (callingPkgSetting.pkg != null
@@ -1282,7 +1305,9 @@
return false;
}
final String targetName = targetPkg.getPackageName();
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "getAppId");
+ if (DEBUG_TRACING) {
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "getAppId");
+ }
final int callingAppId;
if (callingPkgSetting != null) {
callingAppId = callingPkgSetting.appId;
@@ -1290,7 +1315,9 @@
callingAppId = callingSharedPkgSettings.valueAt(0).appId; // all should be the same
}
final int targetAppId = targetPkgSetting.appId;
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ if (DEBUG_TRACING) {
+ Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ }
if (callingAppId == targetAppId) {
if (DEBUG_LOGGING) {
log(callingSetting, targetPkgSetting, "same app id");
@@ -1299,7 +1326,9 @@
}
try {
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "requestsQueryAllPackages");
+ if (DEBUG_TRACING) {
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "requestsQueryAllPackages");
+ }
if (callingPkgSetting != null) {
if (callingPkgSetting.pkg != null
&& requestsQueryAllPackages(callingPkgSetting.pkg)) {
@@ -1314,10 +1343,14 @@
}
}
} finally {
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ if (DEBUG_TRACING) {
+ Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ }
}
try {
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "mForceQueryable");
+ if (DEBUG_TRACING) {
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "mForceQueryable");
+ }
if (mForceQueryable.contains(targetAppId)) {
if (DEBUG_LOGGING) {
log(callingSetting, targetPkgSetting, "force queryable");
@@ -1325,10 +1358,14 @@
return false;
}
} finally {
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ if (DEBUG_TRACING) {
+ Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ }
}
try {
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "mQueriesViaPackage");
+ if (DEBUG_TRACING) {
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "mQueriesViaPackage");
+ }
if (mQueriesViaPackage.contains(callingAppId, targetAppId)) {
if (DEBUG_LOGGING) {
log(callingSetting, targetPkgSetting, "queries package");
@@ -1336,10 +1373,14 @@
return false;
}
} finally {
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ if (DEBUG_TRACING) {
+ Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ }
}
try {
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "mQueriesViaComponent");
+ if (DEBUG_TRACING) {
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "mQueriesViaComponent");
+ }
if (mQueriesViaComponentRequireRecompute) {
mStateProvider.runWithState((settings, users) -> {
recomputeComponentVisibility(settings);
@@ -1352,11 +1393,15 @@
return false;
}
} finally {
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ if (DEBUG_TRACING) {
+ Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ }
}
try {
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "mImplicitlyQueryable");
+ if (DEBUG_TRACING) {
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "mImplicitlyQueryable");
+ }
final int targetUid = UserHandle.getUid(targetUserId, targetAppId);
if (mImplicitlyQueryable.contains(callingUid, targetUid)) {
if (DEBUG_LOGGING) {
@@ -1365,11 +1410,15 @@
return false;
}
} finally {
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ if (DEBUG_TRACING) {
+ Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ }
}
try {
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "mOverlayReferenceMapper");
+ if (DEBUG_TRACING) {
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "mOverlayReferenceMapper");
+ }
if (callingSharedPkgSettings != null) {
int size = callingSharedPkgSettings.size();
for (int index = 0; index < size; index++) {
@@ -1392,11 +1441,15 @@
}
}
} finally {
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ if (DEBUG_TRACING) {
+ Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ }
}
try {
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "mQueryableViaUsesLibrary");
+ if (DEBUG_TRACING) {
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "mQueryableViaUsesLibrary");
+ }
if (mQueryableViaUsesLibrary.contains(callingAppId, targetAppId)) {
if (DEBUG_LOGGING) {
log(callingSetting, targetPkgSetting, "queryable for library users");
@@ -1404,12 +1457,16 @@
return false;
}
} finally {
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ if (DEBUG_TRACING) {
+ Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ }
}
return true;
} finally {
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ if (DEBUG_TRACING) {
+ Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ }
}
}
@@ -1425,7 +1482,9 @@
private static boolean pkgInstruments(
@NonNull AndroidPackage source, @NonNull AndroidPackage target) {
try {
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "pkgInstruments");
+ if (DEBUG_TRACING) {
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "pkgInstruments");
+ }
final String packageName = target.getPackageName();
final List<ParsedInstrumentation> inst = source.getInstrumentations();
for (int i = ArrayUtils.size(inst) - 1; i >= 0; i--) {
@@ -1435,7 +1494,9 @@
}
return false;
} finally {
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ if (DEBUG_TRACING) {
+ Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ }
}
}
diff --git a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
index 1d73abc..c1209d4 100644
--- a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
+++ b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
@@ -288,7 +288,9 @@
if (targetUserProfiles.isEmpty()) {
return false;
}
- return hasCallerGotInteractAcrossProfilesPermission(callingPackage);
+ return hasCallerGotInteractAcrossProfilesPermission(callingPackage)
+ && haveProfilesGotInteractAcrossProfilesPermission(
+ callingPackage, targetUserProfiles);
}
private boolean hasCallerGotInteractAcrossProfilesPermission(String callingPackage) {
@@ -296,6 +298,28 @@
callingPackage, mInjector.getCallingUid(), mInjector.getCallingPid());
}
+ private boolean haveProfilesGotInteractAcrossProfilesPermission(
+ String packageName, List<UserHandle> profiles) {
+ for (UserHandle profile : profiles) {
+ final int uid = mInjector.withCleanCallingIdentity(() -> {
+ try {
+ return mInjector.getPackageManager().getPackageUidAsUser(
+ packageName, /* flags= */ 0, profile.getIdentifier());
+ } catch (PackageManager.NameNotFoundException e) {
+ return -1;
+ }
+ });
+ if (uid == -1) {
+ return false;
+ }
+ if (!hasInteractAcrossProfilesPermission(
+ packageName, uid, PermissionChecker.PID_UNKNOWN)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
private boolean isCrossProfilePackageAllowlisted(String packageName) {
return mInjector.withCleanCallingIdentity(() ->
mInjector.getDevicePolicyManagerInternal()
@@ -482,16 +506,16 @@
// this particular app-op to be modified without the broader app-op permissions.
mInjector.withCleanCallingIdentity(() ->
mInjector.getAppOpsManager()
- .setMode(OP_INTERACT_ACROSS_PROFILES, uid, packageName, newMode));
+ .setUidMode(OP_INTERACT_ACROSS_PROFILES, uid, newMode));
} else {
mInjector.getAppOpsManager()
- .setMode(OP_INTERACT_ACROSS_PROFILES, uid, packageName, newMode);
+ .setUidMode(OP_INTERACT_ACROSS_PROFILES, uid, newMode);
}
// Kill the UID before sending the broadcast to ensure that apps can be informed when
// their app-op has been revoked.
maybeKillUid(packageName, uid, hadPermission);
- sendCanInteractAcrossProfilesChangedBroadcast(packageName, uid, UserHandle.of(profileId));
- maybeLogSetInteractAcrossProfilesAppOp(packageName, newMode, logMetrics, uid);
+ sendCanInteractAcrossProfilesChangedBroadcast(packageName, UserHandle.of(profileId));
+ maybeLogSetInteractAcrossProfilesAppOp(packageName, newMode, logMetrics);
}
/**
@@ -509,7 +533,7 @@
}
private void maybeLogSetInteractAcrossProfilesAppOp(
- String packageName, @Mode int newMode, boolean logMetrics, int uid) {
+ String packageName, @Mode int newMode, boolean logMetrics) {
if (!logMetrics) {
return;
}
@@ -517,7 +541,7 @@
.createEvent(DevicePolicyEnums.SET_INTERACT_ACROSS_PROFILES_APP_OP)
.setStrings(packageName)
.setInt(newMode)
- .setBoolean(appDeclaresCrossProfileAttribute(uid))
+ .setBoolean(appDeclaresCrossProfileAttribute(packageName))
.write();
}
@@ -533,10 +557,10 @@
}
private void sendCanInteractAcrossProfilesChangedBroadcast(
- String packageName, int uid, UserHandle userHandle) {
+ String packageName, UserHandle userHandle) {
final Intent intent =
new Intent(ACTION_CAN_INTERACT_ACROSS_PROFILES_CHANGED).setPackage(packageName);
- if (appDeclaresCrossProfileAttribute(uid)) {
+ if (appDeclaresCrossProfileAttribute(packageName)) {
intent.addFlags(
Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND | Intent.FLAG_RECEIVER_FOREGROUND);
} else {
@@ -553,8 +577,8 @@
.queryBroadcastReceiversAsUser(intent, /* flags= */ 0, userHandle);
}
- private boolean appDeclaresCrossProfileAttribute(int uid) {
- return mInjector.getPackageManagerInternal().getPackage(uid).isCrossProfile();
+ private boolean appDeclaresCrossProfileAttribute(String packageName) {
+ return mInjector.getPackageManagerInternal().getPackage(packageName).isCrossProfile();
}
@Override
diff --git a/services/core/java/com/android/server/pm/CrossProfileIntentResolver.java b/services/core/java/com/android/server/pm/CrossProfileIntentResolver.java
index 7927538..9ea16d3 100644
--- a/services/core/java/com/android/server/pm/CrossProfileIntentResolver.java
+++ b/services/core/java/com/android/server/pm/CrossProfileIntentResolver.java
@@ -19,7 +19,6 @@
import android.annotation.NonNull;
import android.content.IntentFilter;
-import com.android.server.WatchedIntentResolver;
import com.android.server.utils.Snappable;
import com.android.server.utils.SnapshotCache;
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 47d1629..de9add0 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -25,6 +25,7 @@
import static android.content.pm.LauncherApps.FLAG_CACHE_NOTIFICATION_SHORTCUTS;
import static android.content.pm.LauncherApps.FLAG_CACHE_PEOPLE_TILE_SHORTCUTS;
+import android.annotation.AppIdInt;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
@@ -1232,12 +1233,12 @@
cookie.user.getIdentifier());
}
- /** Returns whether or not the given UID is in allow list */
- private static boolean isCallingUidAllowed(int[] allowList, int callingUid) {
- if (allowList == null) {
+ /** Returns whether or not the given appId is in allow list */
+ private static boolean isCallingAppIdAllowed(int[] appIdAllowList, @AppIdInt int appId) {
+ if (appIdAllowList == null) {
return true;
}
- return Arrays.binarySearch(allowList, callingUid) > -1;
+ return Arrays.binarySearch(appIdAllowList, appId) > -1;
}
private String[] getFilteredPackageNames(String[] packageNames, BroadcastCookie cookie) {
@@ -1432,7 +1433,7 @@
// Handle onPackageRemoved.
if (Intent.ACTION_PACKAGE_REMOVED_INTERNAL.equals(action)) {
final String packageName = getPackageName(intent);
- final int[] allowList =
+ final int[] appIdAllowList =
intent.getIntArrayExtra(Intent.EXTRA_VISIBILITY_ALLOW_LIST);
// If {@link #EXTRA_REPLACING} is true, that will be onPackageChanged case.
if (packageName != null && !intent.getBooleanExtra(
@@ -1448,7 +1449,8 @@
if (!isEnabledProfileOf(cookie.user, user, "onPackageRemoved")) {
continue;
}
- if (!isCallingUidAllowed(allowList, cookie.callingUid)) {
+ if (!isCallingAppIdAllowed(appIdAllowList, UserHandle.getAppId(
+ cookie.callingUid))) {
continue;
}
try {
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 6f4ec82..83eb093 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -3762,13 +3762,6 @@
}
}
- final DataLoaderManager dataLoaderManager = mContext.getSystemService(
- DataLoaderManager.class);
- if (dataLoaderManager == null) {
- throw new PackageManagerException(INSTALL_FAILED_MEDIA_UNAVAILABLE,
- "Failed to find data loader manager service");
- }
-
final DataLoaderParams params = this.params.dataLoaderParams;
final boolean manualStartAndDestroy = !isIncrementalInstallation();
final boolean systemDataLoader = isSystemDataLoaderInstallation();
@@ -3793,20 +3786,13 @@
return;
}
try {
- IDataLoader dataLoader = dataLoaderManager.getDataLoader(dataLoaderId);
- if (dataLoader == null) {
- mDataLoaderFinished = true;
- dispatchSessionValidationFailure(INSTALL_FAILED_MEDIA_UNAVAILABLE,
- "Failure to obtain data loader");
- return;
- }
-
switch (status) {
case IDataLoaderStatusListener.DATA_LOADER_BOUND: {
if (manualStartAndDestroy) {
FileSystemControlParcel control = new FileSystemControlParcel();
control.callback = new FileSystemConnector(addedFiles);
- dataLoader.create(dataLoaderId, params.getData(), control, this);
+ getDataLoader(dataLoaderId).create(dataLoaderId, params.getData(),
+ control, this);
}
break;
@@ -3815,12 +3801,12 @@
if (manualStartAndDestroy) {
// IncrementalFileStorages will call start after all files are
// created in IncFS.
- dataLoader.start(dataLoaderId);
+ getDataLoader(dataLoaderId).start(dataLoaderId);
}
break;
}
case IDataLoaderStatusListener.DATA_LOADER_STARTED: {
- dataLoader.prepareImage(
+ getDataLoader(dataLoaderId).prepareImage(
dataLoaderId,
addedFiles.toArray(
new InstallationFileParcel[addedFiles.size()]),
@@ -3836,7 +3822,7 @@
dispatchSessionSealed();
}
if (manualStartAndDestroy) {
- dataLoader.destroy(dataLoaderId);
+ getDataLoader(dataLoaderId).destroy(dataLoaderId);
}
break;
}
@@ -3845,7 +3831,7 @@
dispatchSessionValidationFailure(INSTALL_FAILED_MEDIA_UNAVAILABLE,
"Failed to prepare image.");
if (manualStartAndDestroy) {
- dataLoader.destroy(dataLoaderId);
+ getDataLoader(dataLoaderId).destroy(dataLoaderId);
}
break;
}
@@ -3860,11 +3846,12 @@
break;
}
case IDataLoaderStatusListener.DATA_LOADER_UNRECOVERABLE:
- mDataLoaderFinished = true;
- dispatchSessionValidationFailure(INSTALL_FAILED_MEDIA_UNAVAILABLE,
+ throw new PackageManagerException(INSTALL_FAILED_MEDIA_UNAVAILABLE,
"DataLoader reported unrecoverable failure.");
- break;
}
+ } catch (PackageManagerException e) {
+ mDataLoaderFinished = true;
+ dispatchSessionValidationFailure(e.error, ExceptionUtils.getCompleteMessage(e));
} catch (RemoteException e) {
// In case of streaming failure we don't want to fail or commit the session.
// Just return from this method and allow caller to commit again.
@@ -3939,7 +3926,7 @@
}
final long bindDelayMs = 0;
- if (!dataLoaderManager.bindToDataLoader(sessionId, params.getData(), bindDelayMs,
+ if (!getDataLoaderManager().bindToDataLoader(sessionId, params.getData(), bindDelayMs,
statusListener)) {
throw new PackageManagerException(INSTALL_FAILED_MEDIA_UNAVAILABLE,
"Failed to initialize data loader");
@@ -3948,6 +3935,24 @@
return false;
}
+ private DataLoaderManager getDataLoaderManager() throws PackageManagerException {
+ DataLoaderManager dataLoaderManager = mContext.getSystemService(DataLoaderManager.class);
+ if (dataLoaderManager == null) {
+ throw new PackageManagerException(INSTALL_FAILED_MEDIA_UNAVAILABLE,
+ "Failed to find data loader manager service");
+ }
+ return dataLoaderManager;
+ }
+
+ private IDataLoader getDataLoader(int dataLoaderId) throws PackageManagerException {
+ IDataLoader dataLoader = getDataLoaderManager().getDataLoader(dataLoaderId);
+ if (dataLoader == null) {
+ throw new PackageManagerException(INSTALL_FAILED_MEDIA_UNAVAILABLE,
+ "Failure to obtain data loader");
+ }
+ return dataLoader;
+ }
+
private void dispatchSessionValidationFailure(int error, String detailMessage) {
mHandler.obtainMessage(MSG_SESSION_VALIDATION_FAILURE, error, -1,
detailMessage).sendToTarget();
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 20ca949..4faa18e 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -1926,20 +1926,13 @@
int flags, int userId);
@NonNull List<ResolveInfo> queryIntentServicesInternal(Intent intent, String resolvedType,
int flags, int userId, int callingUid, boolean includeInstantApps);
- @NonNull List<ResolveInfo> queryIntentServicesInternalBody(Intent intent,
- String resolvedType, int flags, int userId, int callingUid,
- String instantAppPkgName);
@NonNull QueryIntentActivitiesResult queryIntentActivitiesInternalBody(Intent intent,
String resolvedType, int flags, int filterCallingUid, int userId,
boolean resolveForStart, boolean allowDynamicSplits, String pkgName,
String instantAppPkgName);
- @Nullable ComponentName findInstallFailureActivity(String packageName, int filterCallingUid,
- int userId);
ActivityInfo getActivityInfo(ComponentName component, int flags, int userId);
ActivityInfo getActivityInfoInternal(ComponentName component, int flags,
int filterCallingUid, int userId);
- ActivityInfo getActivityInfoInternalBody(ComponentName component, int flags,
- int filterCallingUid, int userId);
AndroidPackage getPackage(String packageName);
AndroidPackage getPackage(int uid);
ApplicationInfo generateApplicationInfoFromSettingsLPw(String packageName, int flags,
@@ -1947,11 +1940,6 @@
ApplicationInfo getApplicationInfo(String packageName, int flags, int userId);
ApplicationInfo getApplicationInfoInternal(String packageName, int flags,
int filterCallingUid, int userId);
- ApplicationInfo getApplicationInfoInternalBody(String packageName, int flags,
- int filterCallingUid, int userId);
- ArrayList<ResolveInfo> filterCandidatesWithDomainPreferredActivitiesLPrBody(Intent intent,
- int matchFlags, List<ResolveInfo> candidates, CrossProfileDomainInfo xpDomainInfo,
- int userId, boolean debug);
ComponentName getDefaultHomeActivity(int userId);
ComponentName getHomeActivitiesAsUser(List<ResolveInfo> allHomeCandidates, int userId);
CrossProfileDomainInfo getCrossProfileDomainPreferredLpr(Intent intent, String resolvedType,
@@ -1962,57 +1950,25 @@
List<ResolveInfo> applyPostResolutionFilter(@NonNull List<ResolveInfo> resolveInfos,
String ephemeralPkgName, boolean allowDynamicSplits, int filterCallingUid,
boolean resolveForStart, int userId, Intent intent);
- List<ResolveInfo> applyPostServiceResolutionFilter(List<ResolveInfo> resolveInfos,
- String instantAppPkgName, @UserIdInt int userId, int filterCallingUid);
- List<ResolveInfo> filterCandidatesWithDomainPreferredActivitiesLPr(Intent intent,
- int matchFlags, List<ResolveInfo> candidates, CrossProfileDomainInfo xpDomainInfo,
- int userId);
- List<ResolveInfo> filterIfNotSystemUser(List<ResolveInfo> resolveInfos, int userId);
- List<ResolveInfo> maybeAddInstantAppInstaller(List<ResolveInfo> result, Intent intent,
- String resolvedType, int flags, int userId, boolean resolveForStart,
- boolean isRequesterInstantApp);
PackageInfo generatePackageInfo(PackageSetting ps, int flags, int userId);
PackageInfo getPackageInfo(String packageName, int flags, int userId);
PackageInfo getPackageInfoInternal(String packageName, long versionCode, int flags,
int filterCallingUid, int userId);
- PackageInfo getPackageInfoInternalBody(String packageName, long versionCode, int flags,
- int filterCallingUid, int userId);
PackageSetting getPackageSetting(String packageName);
PackageSetting getPackageSettingInternal(String packageName, int callingUid);
ParceledListSlice<PackageInfo> getInstalledPackages(int flags, int userId);
- ParceledListSlice<PackageInfo> getInstalledPackagesBody(int flags, int userId,
- int callingUid);
- ResolveInfo createForwardingResolveInfo(CrossProfileIntentFilter filter, Intent intent,
- String resolvedType, int flags, int sourceUserId);
ResolveInfo createForwardingResolveInfoUnchecked(WatchedIntentFilter filter,
int sourceUserId, int targetUserId);
- ResolveInfo queryCrossProfileIntents(List<CrossProfileIntentFilter> matchingFilters,
- Intent intent, String resolvedType, int flags, int sourceUserId,
- boolean matchInCurrentProfile);
- ResolveInfo querySkipCurrentProfileIntents(List<CrossProfileIntentFilter> matchingFilters,
- Intent intent, String resolvedType, int flags, int sourceUserId);
ServiceInfo getServiceInfo(ComponentName component, int flags, int userId);
- ServiceInfo getServiceInfoBody(ComponentName component, int flags, int userId,
- int callingUid);
SharedLibraryInfo getSharedLibraryInfoLPr(String name, long version);
String getInstantAppPackageName(int callingUid);
String resolveExternalPackageNameLPr(AndroidPackage pkg);
- String resolveInternalPackageNameInternalLocked(String packageName, long versionCode,
- int callingUid);
String resolveInternalPackageNameLPr(String packageName, long versionCode);
String[] getPackagesForUid(int uid);
- String[] getPackagesForUidInternal(int uid, int callingUid);
- String[] getPackagesForUidInternalBody(int callingUid, int userId, int appId,
- boolean isCallerInstantApp);
UserInfo getProfileParent(int userId);
- boolean areWebInstantAppsDisabled(int userId);
boolean canViewInstantApps(int callingUid, int userId);
boolean filterSharedLibPackageLPr(@Nullable PackageSetting ps, int uid, int userId,
int flags);
- boolean hasCrossUserPermission(int callingUid, int callingUserId, int userId,
- boolean requireFullPermission, boolean requirePermissionWhenSameUser);
- boolean hasNonNegativePriority(List<ResolveInfo> resolveInfos);
- boolean hasPermission(String permission);
boolean isCallerSameApp(String packageName, int uid);
boolean isComponentVisibleToInstantApp(@Nullable ComponentName component);
boolean isComponentVisibleToInstantApp(@Nullable ComponentName component,
@@ -2021,27 +1977,15 @@
String resolvedType, int flags);
boolean isInstantApp(String packageName, int userId);
boolean isInstantAppInternal(String packageName, @UserIdInt int userId, int callingUid);
- boolean isInstantAppInternalBody(String packageName, @UserIdInt int userId, int callingUid);
- boolean isInstantAppResolutionAllowed(Intent intent, List<ResolveInfo> resolvedActivities,
- int userId, boolean skipPackageCheck, int flags);
- boolean isInstantAppResolutionAllowedBody(Intent intent,
- List<ResolveInfo> resolvedActivities, int userId, boolean skipPackageCheck,
- int flags);
- boolean isPersistentPreferredActivitySetByDpm(Intent intent, int userId,
- String resolvedType, int flags);
- boolean isRecentsAccessingChildProfiles(int callingUid, int targetUserId);
boolean isSameProfileGroup(@UserIdInt int callerUserId, @UserIdInt int userId);
- boolean isUserEnabled(int userId);
boolean shouldFilterApplicationLocked(@Nullable PackageSetting ps, int callingUid,
@Nullable ComponentName component, @ComponentType int componentType, int userId);
boolean shouldFilterApplicationLocked(@Nullable PackageSetting ps, int callingUid,
int userId);
boolean shouldFilterApplicationLocked(@NonNull SharedUserSetting sus, int callingUid,
int userId);
- int bestDomainVerificationStatus(int status1, int status2);
int checkUidPermission(String permName, int uid);
int getPackageUidInternal(String packageName, int flags, int userId, int callingUid);
- int updateFlags(int flags, int userId);
int updateFlagsForApplication(int flags, int userId);
int updateFlagsForComponent(int flags, int userId);
int updateFlagsForPackage(int flags, int userId);
@@ -2348,7 +2292,7 @@
userId, callingUid, instantAppPkgName);
}
- public @NonNull List<ResolveInfo> queryIntentServicesInternalBody(Intent intent,
+ protected @NonNull List<ResolveInfo> queryIntentServicesInternalBody(Intent intent,
String resolvedType, int flags, int userId, int callingUid,
String instantAppPkgName) {
// reader
@@ -2486,7 +2430,7 @@
* creating an activity with an intent filter that handles the action
* {@link Intent#ACTION_INSTALL_FAILURE}.
*/
- public @Nullable ComponentName findInstallFailureActivity(
+ private @Nullable ComponentName findInstallFailureActivity(
String packageName, int filterCallingUid, int userId) {
final Intent failureActivityIntent = new Intent(Intent.ACTION_INSTALL_FAILURE);
failureActivityIntent.setPackage(packageName);
@@ -2532,7 +2476,7 @@
return getActivityInfoInternalBody(component, flags, filterCallingUid, userId);
}
- public ActivityInfo getActivityInfoInternalBody(ComponentName component, int flags,
+ protected ActivityInfo getActivityInfoInternalBody(ComponentName component, int flags,
int filterCallingUid, int userId) {
ParsedActivity a = mComponentResolver.getActivity(component);
@@ -2624,7 +2568,7 @@
return getApplicationInfoInternalBody(packageName, flags, filterCallingUid, userId);
}
- public ApplicationInfo getApplicationInfoInternalBody(String packageName, int flags,
+ protected ApplicationInfo getApplicationInfoInternalBody(String packageName, int flags,
int filterCallingUid, int userId) {
// writer
// Normalize package name to handle renamed packages and static libs
@@ -2678,7 +2622,7 @@
return null;
}
- public ArrayList<ResolveInfo> filterCandidatesWithDomainPreferredActivitiesLPrBody(
+ protected ArrayList<ResolveInfo> filterCandidatesWithDomainPreferredActivitiesLPrBody(
Intent intent, int matchFlags, List<ResolveInfo> candidates,
CrossProfileDomainInfo xpDomainInfo, int userId, boolean debug) {
final ArrayList<ResolveInfo> result = new ArrayList<>();
@@ -3017,7 +2961,7 @@
return resolveInfos;
}
- public List<ResolveInfo> applyPostServiceResolutionFilter(List<ResolveInfo> resolveInfos,
+ private List<ResolveInfo> applyPostServiceResolutionFilter(List<ResolveInfo> resolveInfos,
String instantAppPkgName, @UserIdInt int userId, int filterCallingUid) {
for (int i = resolveInfos.size() - 1; i >= 0; i--) {
final ResolveInfo info = resolveInfos.get(i);
@@ -3105,7 +3049,8 @@
*
* @return filtered list
*/
- public List<ResolveInfo> filterIfNotSystemUser(List<ResolveInfo> resolveInfos, int userId) {
+ private List<ResolveInfo> filterIfNotSystemUser(List<ResolveInfo> resolveInfos,
+ int userId) {
if (userId == UserHandle.USER_SYSTEM) {
return resolveInfos;
}
@@ -3118,7 +3063,7 @@
return resolveInfos;
}
- public List<ResolveInfo> maybeAddInstantAppInstaller(List<ResolveInfo> result,
+ private List<ResolveInfo> maybeAddInstantAppInstaller(List<ResolveInfo> result,
Intent intent,
String resolvedType, int flags, int userId, boolean resolveForStart,
boolean isRequesterInstantApp) {
@@ -3314,7 +3259,7 @@
userId);
}
- public PackageInfo getPackageInfoInternalBody(String packageName, long versionCode,
+ protected PackageInfo getPackageInfoInternalBody(String packageName, long versionCode,
int flags, int filterCallingUid, int userId) {
// reader
// Normalize package name to handle renamed packages and static libs
@@ -3398,7 +3343,7 @@
return getInstalledPackagesBody(flags, userId, callingUid);
}
- public ParceledListSlice<PackageInfo> getInstalledPackagesBody(int flags, int userId,
+ protected ParceledListSlice<PackageInfo> getInstalledPackagesBody(int flags, int userId,
int callingUid) {
// writer
final boolean listUninstalled = (flags & MATCH_KNOWN_PACKAGES) != 0;
@@ -3473,7 +3418,7 @@
* will forward the intent to the filter's target user.
* Otherwise, returns null.
*/
- public ResolveInfo createForwardingResolveInfo(CrossProfileIntentFilter filter,
+ private ResolveInfo createForwardingResolveInfo(CrossProfileIntentFilter filter,
Intent intent,
String resolvedType, int flags, int sourceUserId) {
int targetUserId = filter.getTargetUserId();
@@ -3528,7 +3473,7 @@
}
// Return matching ResolveInfo in target user if any.
- public ResolveInfo queryCrossProfileIntents(
+ private ResolveInfo queryCrossProfileIntents(
List<CrossProfileIntentFilter> matchingFilters, Intent intent, String resolvedType,
int flags, int sourceUserId, boolean matchInCurrentProfile) {
if (matchingFilters != null) {
@@ -3558,7 +3503,7 @@
return null;
}
- public ResolveInfo querySkipCurrentProfileIntents(
+ private ResolveInfo querySkipCurrentProfileIntents(
List<CrossProfileIntentFilter> matchingFilters, Intent intent, String resolvedType,
int flags, int sourceUserId) {
if (matchingFilters != null) {
@@ -3589,7 +3534,7 @@
return getServiceInfoBody(component, flags, userId, callingUid);
}
- public ServiceInfo getServiceInfoBody(ComponentName component, int flags, int userId,
+ protected ServiceInfo getServiceInfoBody(ComponentName component, int flags, int userId,
int callingUid) {
ParsedService s = mComponentResolver.getService(component);
if (DEBUG_PACKAGE_INFO) Log.v(
@@ -3656,7 +3601,7 @@
return pkg.getPackageName();
}
- public String resolveInternalPackageNameInternalLocked(
+ private String resolveInternalPackageNameInternalLocked(
String packageName, long versionCode, int callingUid) {
// Handle renamed packages
String normalizedPackageName = mSettings.getRenamedPackageLPr(packageName);
@@ -3748,14 +3693,14 @@
return getPackagesForUidInternal(uid, Binder.getCallingUid());
}
- public String[] getPackagesForUidInternal(int uid, int callingUid) {
+ private String[] getPackagesForUidInternal(int uid, int callingUid) {
final boolean isCallerInstantApp = getInstantAppPackageName(callingUid) != null;
final int userId = UserHandle.getUserId(uid);
final int appId = UserHandle.getAppId(uid);
return getPackagesForUidInternalBody(callingUid, userId, appId, isCallerInstantApp);
}
- public String[] getPackagesForUidInternalBody(int callingUid, int userId, int appId,
+ protected String[] getPackagesForUidInternalBody(int callingUid, int userId, int appId,
boolean isCallerInstantApp) {
// reader
final Object obj = mSettings.getSettingLPr(appId);
@@ -3797,7 +3742,7 @@
/**
* Returns whether or not instant apps have been disabled remotely.
*/
- public boolean areWebInstantAppsDisabled(int userId) {
+ private boolean areWebInstantAppsDisabled(int userId) {
return mWebInstantAppsDisabled.get(userId);
}
@@ -3894,7 +3839,7 @@
return true;
}
- public boolean hasCrossUserPermission(
+ private boolean hasCrossUserPermission(
int callingUid, int callingUserId, int userId, boolean requireFullPermission,
boolean requirePermissionWhenSameUser) {
if (!requirePermissionWhenSameUser && userId == callingUserId) {
@@ -3914,11 +3859,11 @@
* @param resolveInfos list of resolve infos in descending priority order
* @return if the list contains a resolve info with non-negative priority
*/
- public boolean hasNonNegativePriority(List<ResolveInfo> resolveInfos) {
+ private boolean hasNonNegativePriority(List<ResolveInfo> resolveInfos) {
return resolveInfos.size() > 0 && resolveInfos.get(0).priority >= 0;
}
- public boolean hasPermission(String permission) {
+ private boolean hasPermission(String permission) {
return mContext.checkCallingOrSelfPermission(permission)
== PackageManager.PERMISSION_GRANTED;
}
@@ -4012,7 +3957,7 @@
return isInstantAppInternalBody(packageName, userId, callingUid);
}
- public boolean isInstantAppInternalBody(String packageName, @UserIdInt int userId,
+ protected boolean isInstantAppInternalBody(String packageName, @UserIdInt int userId,
int callingUid) {
if (Process.isIsolated(callingUid)) {
callingUid = getIsolatedOwner(callingUid);
@@ -4030,7 +3975,7 @@
return false;
}
- public boolean isInstantAppResolutionAllowed(
+ private boolean isInstantAppResolutionAllowed(
Intent intent, List<ResolveInfo> resolvedActivities, int userId,
boolean skipPackageCheck, int flags) {
if (mInstantAppResolverConnection == null) {
@@ -4070,7 +4015,7 @@
// Deny ephemeral apps if the user chose _ALWAYS or _ALWAYS_ASK for intent resolution.
// Or if there's already an ephemeral app installed that handles the action
- public boolean isInstantAppResolutionAllowedBody(
+ protected boolean isInstantAppResolutionAllowedBody(
Intent intent, List<ResolveInfo> resolvedActivities, int userId,
boolean skipPackageCheck, int flags) {
final int count = (resolvedActivities == null ? 0 : resolvedActivities.size());
@@ -4103,7 +4048,7 @@
return true;
}
- public boolean isPersistentPreferredActivitySetByDpm(Intent intent, int userId,
+ private boolean isPersistentPreferredActivitySetByDpm(Intent intent, int userId,
String resolvedType, int flags) {
PersistentPreferredIntentResolver ppir =
mSettings.getPersistentPreferredActivities(userId);
@@ -4121,7 +4066,7 @@
return false;
}
- public boolean isRecentsAccessingChildProfiles(int callingUid, int targetUserId) {
+ private boolean isRecentsAccessingChildProfiles(int callingUid, int targetUserId) {
if (!mInjector.getLocalService(ActivityTaskManagerInternal.class)
.isCallerRecents(callingUid)) {
return false;
@@ -4147,7 +4092,7 @@
}
}
- public boolean isUserEnabled(int userId) {
+ private boolean isUserEnabled(int userId) {
final long callingId = Binder.clearCallingIdentity();
try {
UserInfo userInfo = mUserManager.getUserInfo(userId);
@@ -4247,7 +4192,7 @@
* Verification statuses are ordered from the worse to the best, except for
* INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER, which is the worse.
*/
- public int bestDomainVerificationStatus(int status1, int status2) {
+ private int bestDomainVerificationStatus(int status1, int status2) {
if (status1 == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER) {
return status2;
}
@@ -4287,7 +4232,7 @@
/**
* Update given flags based on encryption status of current user.
*/
- public int updateFlags(int flags, int userId) {
+ private int updateFlags(int flags, int userId) {
if ((flags & (PackageManager.MATCH_DIRECT_BOOT_UNAWARE
| PackageManager.MATCH_DIRECT_BOOT_AWARE)) != 0) {
// Caller expressed an explicit opinion about what encryption
@@ -7892,12 +7837,6 @@
flags, filterCallingUid, userId);
}
- private PackageInfo getPackageInfoInternalBody(String packageName, long versionCode,
- int flags, int filterCallingUid, int userId) {
- return liveComputer().getPackageInfoInternalBody(packageName, versionCode,
- flags, filterCallingUid, userId);
- }
-
private boolean isComponentVisibleToInstantApp(@Nullable ComponentName component) {
return liveComputer().isComponentVisibleToInstantApp(component);
}
@@ -8084,12 +8023,6 @@
filterCallingUid, userId);
}
- private ApplicationInfo getApplicationInfoInternalBody(String packageName, int flags,
- int filterCallingUid, int userId) {
- return liveComputer().getApplicationInfoInternalBody(packageName, flags,
- filterCallingUid, userId);
- }
-
@GuardedBy("mLock")
private String normalizePackageNameLPr(String packageName) {
String normalizedPackageName = mSettings.getRenamedPackageLPr(packageName);
@@ -8317,13 +8250,6 @@
}
/**
- * Update given flags based on encryption status of current user.
- */
- private int updateFlags(int flags, int userId) {
- return liveComputer().updateFlags(flags, userId);
- }
-
- /**
* Update given flags when being used to request {@link PackageInfo}.
*/
private int updateFlagsForPackage(int flags, int userId) {
@@ -8417,16 +8343,6 @@
filterCallingUid, userId);
}
- private ActivityInfo getActivityInfoInternalBody(ComponentName component, int flags,
- int filterCallingUid, int userId) {
- return liveComputer().getActivityInfoInternalBody(component, flags,
- filterCallingUid, userId);
- }
-
- private boolean isRecentsAccessingChildProfiles(int callingUid, int targetUserId) {
- return liveComputer().isRecentsAccessingChildProfiles(callingUid, targetUserId);
- }
-
@Override
public boolean activitySupportsIntent(ComponentName component, Intent intent,
String resolvedType) {
@@ -8692,12 +8608,6 @@
return snapshotComputer().getServiceInfo(component, flags, userId);
}
- private ServiceInfo getServiceInfoBody(ComponentName component, int flags, int userId,
- int callingUid) {
- return liveComputer().getServiceInfoBody(component, flags, userId,
- callingUid);
- }
-
@Override
public ProviderInfo getProviderInfo(ComponentName component, int flags, int userId) {
if (!mUserManager.exists(userId)) return null;
@@ -9245,16 +9155,6 @@
return snapshotComputer().getPackagesForUid(uid);
}
- private String[] getPackagesForUidInternal(int uid, int callingUid) {
- return liveComputer().getPackagesForUidInternal(uid, callingUid);
- }
-
- private String[] getPackagesForUidInternalBody(int callingUid, int userId, int appId,
- boolean isCallerInstantApp) {
- return liveComputer().getPackagesForUidInternalBody(callingUid, userId, appId,
- isCallerInstantApp);
- }
-
@Override
public String getNameForUid(int uid) {
final int callingUid = Binder.getCallingUid();
@@ -9558,31 +9458,6 @@
intent, resolvedType, flags, query, 0, false, false, false, userId);
}
- /**
- * Returns whether or not instant apps have been disabled remotely.
- */
- private boolean areWebInstantAppsDisabled(int userId) {
- return liveComputer().areWebInstantAppsDisabled(userId);
- }
-
- private boolean isInstantAppResolutionAllowed(
- Intent intent, List<ResolveInfo> resolvedActivities, int userId,
- boolean skipPackageCheck, int flags) {
- return liveComputer().isInstantAppResolutionAllowed(
- intent, resolvedActivities, userId,
- skipPackageCheck, flags);
- }
-
- // Deny ephemeral apps if the user chose _ALWAYS or _ALWAYS_ASK for intent resolution.
- // Or if there's already an ephemeral app installed that handles the action
- private boolean isInstantAppResolutionAllowedBody(
- Intent intent, List<ResolveInfo> resolvedActivities, int userId,
- boolean skipPackageCheck, int flags) {
- return liveComputer().isInstantAppResolutionAllowedBody(
- intent, resolvedActivities, userId,
- skipPackageCheck, flags);
- }
-
private void requestInstantAppResolutionPhaseTwo(AuxiliaryResolveInfo responseObj,
Intent origIntent, String resolvedType, String callingPackage,
@Nullable String callingFeatureId, boolean isRequesterInstantApp,
@@ -9734,12 +9609,6 @@
resolvedType, flags);
}
- private boolean isPersistentPreferredActivitySetByDpm(Intent intent, int userId,
- String resolvedType, int flags) {
- return liveComputer().isPersistentPreferredActivitySetByDpm(intent, userId,
- resolvedType, flags);
- }
-
@GuardedBy("mLock")
private ResolveInfo findPersistentPreferredActivityLP(Intent intent, String resolvedType,
int flags, List<ResolveInfo> query, boolean debug, int userId) {
@@ -10133,14 +10002,6 @@
instantAppPkgName);
}
- private List<ResolveInfo> maybeAddInstantAppInstaller(List<ResolveInfo> result, Intent intent,
- String resolvedType, int flags, int userId, boolean resolveForStart,
- boolean isRequesterInstantApp) {
- return liveComputer().maybeAddInstantAppInstaller(result, intent,
- resolvedType, flags, userId, resolveForStart,
- isRequesterInstantApp);
- }
-
private static class CrossProfileDomainInfo {
/* ResolveInfo for IntentForwarderActivity to send the intent to the other profile */
ResolveInfo resolveInfo;
@@ -10154,27 +10015,6 @@
}
/**
- * Verification statuses are ordered from the worse to the best, except for
- * INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER, which is the worse.
- */
- private int bestDomainVerificationStatus(int status1, int status2) {
- return liveComputer().bestDomainVerificationStatus(status1, status2);
- }
-
- private boolean isUserEnabled(int userId) {
- return liveComputer().isUserEnabled(userId);
- }
-
- /**
- * Filter out activities with systemUserOnly flag set, when current user is not System.
- *
- * @return filtered list
- */
- private List<ResolveInfo> filterIfNotSystemUser(List<ResolveInfo> resolveInfos, int userId) {
- return liveComputer().filterIfNotSystemUser(resolveInfos, userId);
- }
-
- /**
* Filters out ephemeral activities.
* <p>When resolving for an ephemeral app, only activities that 1) are defined in the
* ephemeral app or 2) marked with {@code visibleToEphemeral} are returned.
@@ -10193,72 +10033,6 @@
resolveForStart, userId, intent);
}
- /**
- * Returns the activity component that can handle install failures.
- * <p>By default, the instant application installer handles failures. However, an
- * application may want to handle failures on its own. Applications do this by
- * creating an activity with an intent filter that handles the action
- * {@link Intent#ACTION_INSTALL_FAILURE}.
- */
- private @Nullable ComponentName findInstallFailureActivity(
- String packageName, int filterCallingUid, int userId) {
- return liveComputer().findInstallFailureActivity(
- packageName, filterCallingUid, userId);
- }
-
- /**
- * @param resolveInfos list of resolve infos in descending priority order
- * @return if the list contains a resolve info with non-negative priority
- */
- private boolean hasNonNegativePriority(List<ResolveInfo> resolveInfos) {
- return liveComputer().hasNonNegativePriority(resolveInfos);
- }
-
- private List<ResolveInfo> filterCandidatesWithDomainPreferredActivitiesLPr(Intent intent,
- int matchFlags, List<ResolveInfo> candidates, CrossProfileDomainInfo xpDomainInfo,
- int userId) {
- return liveComputer().filterCandidatesWithDomainPreferredActivitiesLPr(intent,
- matchFlags, candidates, xpDomainInfo,
- userId);
- }
-
- private ArrayList<ResolveInfo> filterCandidatesWithDomainPreferredActivitiesLPrBody(
- Intent intent, int matchFlags, List<ResolveInfo> candidates,
- CrossProfileDomainInfo xpDomainInfo, int userId, boolean debug) {
- return liveComputer().filterCandidatesWithDomainPreferredActivitiesLPrBody(
- intent, matchFlags, candidates,
- xpDomainInfo, userId, debug);
- }
-
-
- private ResolveInfo querySkipCurrentProfileIntents(
- List<CrossProfileIntentFilter> matchingFilters, Intent intent, String resolvedType,
- int flags, int sourceUserId) {
- return liveComputer().querySkipCurrentProfileIntents(
- matchingFilters, intent, resolvedType,
- flags, sourceUserId);
- }
-
- // Return matching ResolveInfo in target user if any.
- private ResolveInfo queryCrossProfileIntents(
- List<CrossProfileIntentFilter> matchingFilters, Intent intent, String resolvedType,
- int flags, int sourceUserId, boolean matchInCurrentProfile) {
- return liveComputer().queryCrossProfileIntents(
- matchingFilters, intent, resolvedType,
- flags, sourceUserId, matchInCurrentProfile);
- }
-
- /**
- * If the filter's target user can handle the intent and is enabled: returns a ResolveInfo that
- * will forward the intent to the filter's target user.
- * Otherwise, returns null.
- */
- private ResolveInfo createForwardingResolveInfo(CrossProfileIntentFilter filter, Intent intent,
- String resolvedType, int flags, int sourceUserId) {
- return liveComputer().createForwardingResolveInfo(filter, intent,
- resolvedType, flags, sourceUserId);
- }
-
@Override
public @NonNull ParceledListSlice<ResolveInfo> queryIntentActivityOptions(ComponentName caller,
Intent[] specifics, String[] specificTypes, Intent intent,
@@ -10580,20 +10354,6 @@
includeInstantApps);
}
- private @NonNull List<ResolveInfo> queryIntentServicesInternalBody(Intent intent,
- String resolvedType, int flags, int userId, int callingUid,
- String instantAppPkgName) {
- return liveComputer().queryIntentServicesInternalBody(intent,
- resolvedType, flags, userId, callingUid,
- instantAppPkgName);
- }
-
- private List<ResolveInfo> applyPostServiceResolutionFilter(List<ResolveInfo> resolveInfos,
- String instantAppPkgName, @UserIdInt int userId, int filterCallingUid) {
- return liveComputer().applyPostServiceResolutionFilter(resolveInfos,
- instantAppPkgName, userId, filterCallingUid);
- }
-
@Override
public @NonNull ParceledListSlice<ResolveInfo> queryIntentContentProviders(Intent intent,
String resolvedType, int flags, int userId) {
@@ -10746,12 +10506,6 @@
return snapshotComputer().getInstalledPackages(flags, userId);
}
- private ParceledListSlice<PackageInfo> getInstalledPackagesBody(int flags, int userId,
- int callingUid) {
- return liveComputer().getInstalledPackagesBody(flags, userId,
- callingUid);
- }
-
private void addPackageHoldingPermissions(ArrayList<PackageInfo> list, PackageSetting ps,
String[] permissions, boolean[] tmp, int flags, int userId) {
int numMatch = 0;
@@ -10935,12 +10689,6 @@
callingUid);
}
- private boolean isInstantAppInternalBody(String packageName, @UserIdInt int userId,
- int callingUid) {
- return liveComputer().isInstantAppInternalBody(packageName, userId,
- callingUid);
- }
-
@Override
public byte[] getInstantAppCookie(String packageName, int userId) {
if (HIDE_EPHEMERAL_APIS) {
@@ -11796,18 +11544,6 @@
requireFullPermission, checkShell, message);
}
- private boolean hasCrossUserPermission(
- int callingUid, int callingUserId, int userId, boolean requireFullPermission,
- boolean requirePermissionWhenSameUser) {
- return liveComputer().hasCrossUserPermission(
- callingUid, callingUserId, userId, requireFullPermission,
- requirePermissionWhenSameUser);
- }
-
- private boolean hasPermission(String permission) {
- return liveComputer().hasPermission(permission);
- }
-
private boolean isSameProfileGroup(@UserIdInt int callerUserId, @UserIdInt int userId) {
return liveComputer().isSameProfileGroup(callerUserId, userId);
}
@@ -20681,12 +20417,6 @@
return liveComputer().resolveInternalPackageNameLPr(packageName, versionCode);
}
- private String resolveInternalPackageNameInternalLocked(
- String packageName, long versionCode, int callingUid) {
- return liveComputer().resolveInternalPackageNameInternalLocked(
- packageName, versionCode, callingUid);
- }
-
boolean isCallerVerifier(int callingUid) {
final int callingUserId = UserHandle.getUserId(callingUid);
return mRequiredVerifierPackage != null &&
@@ -26784,8 +26514,10 @@
}
@Override
- public void setDeviceOwnerProtectedPackages(List<String> packageNames) {
- mProtectedPackages.setDeviceOwnerProtectedPackages(packageNames);
+ public void setDeviceOwnerProtectedPackages(
+ String deviceOwnerPackageName, List<String> packageNames) {
+ mProtectedPackages.setDeviceOwnerProtectedPackages(
+ deviceOwnerPackageName, packageNames);
}
@Override
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommandDataLoader.java b/services/core/java/com/android/server/pm/PackageManagerShellCommandDataLoader.java
index 1814a8e..a1e5153 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommandDataLoader.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommandDataLoader.java
@@ -33,9 +33,12 @@
import java.io.IOException;
import java.lang.ref.WeakReference;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.Collection;
+import java.util.concurrent.atomic.AtomicLong;
/**
* Callback data loader for PackageManagerShellCommand installations.
@@ -136,6 +139,12 @@
private final byte mMode;
private final String mData;
+ private final String mSalt;
+
+ private static AtomicLong sGlobalSalt = new AtomicLong((new SecureRandom()).nextLong());
+ private static Long nextGlobalSalt() {
+ return sGlobalSalt.incrementAndGet();
+ }
static Metadata forStdIn(String fileId) {
return new Metadata(STDIN, fileId);
@@ -144,7 +153,7 @@
/** @hide */
@VisibleForTesting
public static Metadata forLocalFile(String filePath) {
- return new Metadata(LOCAL_FILE, filePath);
+ return new Metadata(LOCAL_FILE, filePath, nextGlobalSalt().toString());
}
static Metadata forDataOnlyStreaming(String fileId) {
@@ -156,26 +165,71 @@
}
private Metadata(byte mode, String data) {
+ this(mode, data, null);
+ }
+
+ private Metadata(byte mode, String data, String salt) {
this.mMode = mode;
this.mData = (data == null) ? "" : data;
+ this.mSalt = salt;
}
static Metadata fromByteArray(byte[] bytes) throws IOException {
- if (bytes == null || bytes.length == 0) {
+ if (bytes == null || bytes.length < 5) {
return null;
}
- byte mode = bytes[0];
- String data = new String(bytes, 1, bytes.length - 1, StandardCharsets.UTF_8);
- return new Metadata(mode, data);
+ int offset = 0;
+ final byte mode = bytes[offset];
+ offset += 1;
+ final String data;
+ final String salt;
+ switch (mode) {
+ case LOCAL_FILE: {
+ int dataSize = ByteBuffer.wrap(bytes, offset, 4).order(
+ ByteOrder.LITTLE_ENDIAN).getInt();
+ offset += 4;
+ data = new String(bytes, offset, dataSize, StandardCharsets.UTF_8);
+ offset += dataSize;
+ salt = new String(bytes, offset, bytes.length - offset,
+ StandardCharsets.UTF_8);
+ break;
+ }
+ default:
+ data = new String(bytes, offset, bytes.length - offset,
+ StandardCharsets.UTF_8);
+ salt = null;
+ break;
+ }
+ return new Metadata(mode, data, salt);
}
/** @hide */
@VisibleForTesting
public byte[] toByteArray() {
- byte[] dataBytes = this.mData.getBytes(StandardCharsets.UTF_8);
- byte[] result = new byte[1 + dataBytes.length];
- result[0] = this.mMode;
- System.arraycopy(dataBytes, 0, result, 1, dataBytes.length);
+ final byte[] result;
+ final byte[] dataBytes = this.mData.getBytes(StandardCharsets.UTF_8);
+ switch (this.mMode) {
+ case LOCAL_FILE: {
+ int dataSize = dataBytes.length;
+ byte[] saltBytes = this.mSalt.getBytes(StandardCharsets.UTF_8);
+ result = new byte[1 + 4 + dataSize + saltBytes.length];
+ int offset = 0;
+ result[offset] = this.mMode;
+ offset += 1;
+ ByteBuffer.wrap(result, offset, 4).order(ByteOrder.LITTLE_ENDIAN).putInt(
+ dataSize);
+ offset += 4;
+ System.arraycopy(dataBytes, 0, result, offset, dataSize);
+ offset += dataSize;
+ System.arraycopy(saltBytes, 0, result, offset, saltBytes.length);
+ break;
+ }
+ default:
+ result = new byte[1 + dataBytes.length];
+ result[0] = this.mMode;
+ System.arraycopy(dataBytes, 0, result, 1, dataBytes.length);
+ break;
+ }
return result;
}
diff --git a/services/core/java/com/android/server/pm/PersistentPreferredIntentResolver.java b/services/core/java/com/android/server/pm/PersistentPreferredIntentResolver.java
index bfddaea..bc65c3a 100644
--- a/services/core/java/com/android/server/pm/PersistentPreferredIntentResolver.java
+++ b/services/core/java/com/android/server/pm/PersistentPreferredIntentResolver.java
@@ -19,7 +19,6 @@
import android.annotation.NonNull;
import android.content.IntentFilter;
-import com.android.server.WatchedIntentResolver;
import com.android.server.utils.Snappable;
import com.android.server.utils.SnapshotCache;
diff --git a/services/core/java/com/android/server/pm/PreferredIntentResolver.java b/services/core/java/com/android/server/pm/PreferredIntentResolver.java
index 0aca6ee..fc7680b 100644
--- a/services/core/java/com/android/server/pm/PreferredIntentResolver.java
+++ b/services/core/java/com/android/server/pm/PreferredIntentResolver.java
@@ -19,7 +19,6 @@
import android.annotation.NonNull;
import android.content.IntentFilter;
-import com.android.server.WatchedIntentResolver;
import com.android.server.utils.Snappable;
import com.android.server.utils.SnapshotCache;
diff --git a/services/core/java/com/android/server/pm/ProtectedPackages.java b/services/core/java/com/android/server/pm/ProtectedPackages.java
index 4da3cc3..bf46129 100644
--- a/services/core/java/com/android/server/pm/ProtectedPackages.java
+++ b/services/core/java/com/android/server/pm/ProtectedPackages.java
@@ -20,14 +20,15 @@
import android.annotation.UserIdInt;
import android.content.Context;
import android.os.UserHandle;
+import android.util.ArrayMap;
+import android.util.ArraySet;
import android.util.SparseArray;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
-import com.android.internal.util.ArrayUtils;
-import java.util.ArrayList;
import java.util.List;
+import java.util.Set;
/**
* Manages package names that need special protection.
@@ -55,7 +56,7 @@
@Nullable
@GuardedBy("this")
- private List<String> mDeviceOwnerProtectedPackages;
+ private final ArrayMap<String, Set<String>> mDeviceOwnerProtectedPackages = new ArrayMap<>();
private final Context mContext;
@@ -78,8 +79,14 @@
: profileOwnerPackages.clone();
}
- public synchronized void setDeviceOwnerProtectedPackages(List<String> packageNames) {
- mDeviceOwnerProtectedPackages = new ArrayList<String>(packageNames);
+ /** Sets the protected packages for the device owner. */
+ public synchronized void setDeviceOwnerProtectedPackages(
+ String deviceOwnerPackageName, List<String> packageNames) {
+ if (packageNames.isEmpty()) {
+ mDeviceOwnerProtectedPackages.remove(deviceOwnerPackageName);
+ } else {
+ mDeviceOwnerProtectedPackages.put(deviceOwnerPackageName, new ArraySet<>(packageNames));
+ }
}
private synchronized boolean hasDeviceOwnerOrProfileOwner(int userId, String packageName) {
@@ -118,7 +125,17 @@
*/
private synchronized boolean isProtectedPackage(String packageName) {
return packageName != null && (packageName.equals(mDeviceProvisioningPackage)
- || ArrayUtils.contains(mDeviceOwnerProtectedPackages, packageName));
+ || isDeviceOwnerProtectedPackage(packageName));
+ }
+
+ /** Returns {@code true} if the given package is a protected package set by any device owner. */
+ private synchronized boolean isDeviceOwnerProtectedPackage(String packageName) {
+ for (Set<String> protectedPackages : mDeviceOwnerProtectedPackages.values()) {
+ if (protectedPackages.contains(packageName)) {
+ return true;
+ }
+ }
+ return false;
}
/**
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index f5a13d5..4bc87a2 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -4471,7 +4471,23 @@
pw.print(prefix); pw.print(" versionCode="); pw.print(ps.versionCode);
if (pkg != null) {
pw.print(" minSdk="); pw.print(pkg.getMinSdkVersion());
- pw.print(" targetSdk="); pw.print(pkg.getTargetSdkVersion());
+ pw.print(" targetSdk="); pw.println(pkg.getTargetSdkVersion());
+
+ SparseIntArray minExtensionVersions = pkg.getMinExtensionVersions();
+
+ pw.print(prefix); pw.print(" minExtensionVersions=[");
+ if (minExtensionVersions != null) {
+ List<String> minExtVerStrings = new ArrayList<>();
+ int size = minExtensionVersions.size();
+ for (int index = 0; index < size; index++) {
+ int key = minExtensionVersions.keyAt(index);
+ int value = minExtensionVersions.valueAt(index);
+ minExtVerStrings.add(key + "=" + value);
+ }
+
+ pw.print(TextUtils.join(", ", minExtVerStrings));
+ }
+ pw.print("]");
}
pw.println();
if (pkg != null) {
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 20f35f2..1e9d7e1 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -1213,7 +1213,9 @@
final String pkg = shortcutInfo.getPackage();
final int userId = shortcutInfo.getUserId();
final String id = shortcutInfo.getId();
- getPackageShortcutsLocked(pkg, userId).mutateShortcut(id, shortcutInfo, cb);
+ synchronized (mLock) {
+ getPackageShortcutsLocked(pkg, userId).mutateShortcut(id, shortcutInfo, cb);
+ }
}
/** Return the last reset time. */
diff --git a/services/core/java/com/android/server/pm/SnapshotStatistics.java b/services/core/java/com/android/server/pm/SnapshotStatistics.java
index 7bf00603..95f80de 100644
--- a/services/core/java/com/android/server/pm/SnapshotStatistics.java
+++ b/services/core/java/com/android/server/pm/SnapshotStatistics.java
@@ -625,7 +625,7 @@
* output.
*/
public void dump(PrintWriter pw, String indent, long now, int unrecorded,
- int corkLevel, boolean full) {
+ int corkLevel, boolean brief) {
// Grab the raw statistics under lock, but print them outside of the lock.
Stats[] l;
Stats[] s;
@@ -639,7 +639,7 @@
unrecorded, corkLevel);
pw.println();
dump(pw, indent, now, l, s, "stats");
- if (!full) {
+ if (brief) {
return;
}
pw.println();
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index ff90043..3a1ffe1 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -138,7 +138,9 @@
UserManager.DISALLOW_AMBIENT_DISPLAY,
UserManager.DISALLOW_CONFIG_SCREEN_TIMEOUT,
UserManager.DISALLOW_PRINTING,
- UserManager.DISALLOW_CONFIG_PRIVATE_DNS
+ UserManager.DISALLOW_CONFIG_PRIVATE_DNS,
+ UserManager.DISALLOW_MICROPHONE_TOGGLE,
+ UserManager.DISALLOW_CAMERA_TOGGLE
});
public static final Set<String> DEPRECATED_USER_RESTRICTIONS = Sets.newArraySet(
@@ -180,7 +182,9 @@
*/
private static final Set<String> DEVICE_OWNER_ONLY_RESTRICTIONS = Sets.newArraySet(
UserManager.DISALLOW_USER_SWITCH,
- UserManager.DISALLOW_CONFIG_PRIVATE_DNS
+ UserManager.DISALLOW_CONFIG_PRIVATE_DNS,
+ UserManager.DISALLOW_MICROPHONE_TOGGLE,
+ UserManager.DISALLOW_CAMERA_TOGGLE
);
/**
diff --git a/services/core/java/com/android/server/WatchedIntentResolver.java b/services/core/java/com/android/server/pm/WatchedIntentResolver.java
similarity index 82%
rename from services/core/java/com/android/server/WatchedIntentResolver.java
rename to services/core/java/com/android/server/pm/WatchedIntentResolver.java
index 0831c36..1c3d884 100644
--- a/services/core/java/com/android/server/WatchedIntentResolver.java
+++ b/services/core/java/com/android/server/pm/WatchedIntentResolver.java
@@ -14,18 +14,20 @@
* limitations under the License.
*/
-package com.android.server;
+package com.android.server.pm;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import com.android.server.pm.WatchedIntentFilter;
+import com.android.server.IntentResolver;
import com.android.server.utils.Snappable;
import com.android.server.utils.Watchable;
import com.android.server.utils.WatchableImpl;
import com.android.server.utils.Watcher;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.List;
/**
@@ -34,7 +36,8 @@
* @param <R> The resolver type.
* {@hide}
*/
-public abstract class WatchedIntentResolver<F extends Watchable, R extends Object>
+public abstract class WatchedIntentResolver<F extends WatchedIntentFilter,
+ R extends WatchedIntentFilter>
extends IntentResolver<F, R>
implements Watchable, Snappable {
@@ -116,11 +119,21 @@
onChanged();
}
+ // Sorts a List of IntentFilter objects into descending priority order.
+ @SuppressWarnings("rawtypes")
+ private static final Comparator<WatchedIntentFilter> sResolvePrioritySorter =
+ new Comparator<>() {
+ public int compare(WatchedIntentFilter o1, WatchedIntentFilter o2) {
+ final int q1 = o1.getPriority();
+ final int q2 = o2.getPriority();
+ return (q1 > q2) ? -1 : ((q1 < q2) ? 1 : 0);
+ }
+ };
+
@Override
@SuppressWarnings("unchecked")
protected void sortResults(List<R> results) {
- super.sortResults(results);
- onChanged();
+ Collections.sort(results, sResolvePrioritySorter);
}
/**
diff --git a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
index 61f51e3..0f67be7 100644
--- a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
+++ b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
@@ -444,6 +444,7 @@
componentInfo.directBootAware = mainComponent.isDirectBootAware();
componentInfo.enabled = mainComponent.isEnabled();
componentInfo.splitName = mainComponent.getSplitName();
+ componentInfo.attributionTags = mainComponent.getAttributionTags();
}
private static void assignStateFieldsForPackageItemInfo(
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index d73203d..c21f72e 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -1072,6 +1072,8 @@
private void powerLongPress(long eventTime) {
final int behavior = getResolvedLongPressOnPowerBehavior();
+ Slog.d(TAG, "powerLongPress: eventTime=" + eventTime
+ + " mLongPressOnPowerBehavior=" + mLongPressOnPowerBehavior);
switch (behavior) {
case LONG_PRESS_POWER_NOTHING:
@@ -5130,6 +5132,7 @@
long[] pattern;
switch (effectId) {
case HapticFeedbackConstants.CONTEXT_CLICK:
+ case HapticFeedbackConstants.GESTURE_END:
return VibrationEffect.get(VibrationEffect.EFFECT_TICK);
case HapticFeedbackConstants.TEXT_HANDLE_MOVE:
if (!mHapticTextHandleEnabled) {
@@ -5142,7 +5145,6 @@
case HapticFeedbackConstants.VIRTUAL_KEY_RELEASE:
case HapticFeedbackConstants.ENTRY_BUMP:
case HapticFeedbackConstants.DRAG_CROSSING:
- case HapticFeedbackConstants.GESTURE_END:
return VibrationEffect.get(VibrationEffect.EFFECT_TICK, false);
case HapticFeedbackConstants.KEYBOARD_TAP: // == KEYBOARD_PRESS
case HapticFeedbackConstants.VIRTUAL_KEY:
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 8991981..3018e5f 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -2957,8 +2957,7 @@
// Group has been removed.
return;
}
- // TODO (b/175764708): Support per-display doze.
- wakefulness = getWakefulnessLocked();
+ wakefulness = mDisplayGroupPowerStateMapper.getWakefulnessLocked(groupId);
if ((wakefulness == WAKEFULNESS_DREAMING || wakefulness == WAKEFULNESS_DOZING) &&
mDisplayGroupPowerStateMapper.isSandmanSummoned(groupId)
&& mDisplayGroupPowerStateMapper.isReady(groupId)) {
@@ -3100,6 +3099,7 @@
* Returns true if the device is allowed to doze in its current state.
*/
private boolean canDozeLocked() {
+ // TODO (b/175764708): Support per-display doze.
return getWakefulnessLocked() == WAKEFULNESS_DOZING;
}
diff --git a/services/core/java/com/android/server/rotationresolver/RotationResolverManagerPerUserService.java b/services/core/java/com/android/server/rotationresolver/RotationResolverManagerPerUserService.java
index 81bf29b..ccf096e 100644
--- a/services/core/java/com/android/server/rotationresolver/RotationResolverManagerPerUserService.java
+++ b/services/core/java/com/android/server/rotationresolver/RotationResolverManagerPerUserService.java
@@ -18,6 +18,7 @@
import static android.service.rotationresolver.RotationResolverService.ROTATION_RESULT_FAILURE_CANCELLED;
+import static com.android.internal.util.LatencyTracker.ACTION_ROTATE_SCREEN_CAMERA_CHECK;
import static com.android.server.rotationresolver.RotationResolverManagerService.RESOLUTION_UNAVAILABLE;
import static com.android.server.rotationresolver.RotationResolverManagerService.logRotationStats;
@@ -38,6 +39,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.LatencyTracker;
import com.android.server.infra.AbstractPerUserSystemService;
/**
@@ -62,10 +64,13 @@
RemoteRotationResolverService mRemoteService;
private ComponentName mComponentName;
+ @GuardedBy("mLock")
+ private LatencyTracker mLatencyTracker;
RotationResolverManagerPerUserService(@NonNull RotationResolverManagerService main,
@NonNull Object lock, @UserIdInt int userId) {
super(main, lock, userId);
+ mLatencyTracker = LatencyTracker.getInstance(getContext());
}
@GuardedBy("mLock")
@@ -108,7 +113,33 @@
cancelLocked();
}
- mCurrentRequest = new RemoteRotationResolverService.RotationRequest(callbackInternal,
+ synchronized (mLock) {
+ mLatencyTracker.onActionStart(ACTION_ROTATE_SCREEN_CAMERA_CHECK);
+ }
+ /** Need to wrap RotationResolverCallbackInternal since there was no other way to hook
+ into the success/failure callback **/
+ final RotationResolverInternal.RotationResolverCallbackInternal wrapper =
+ new RotationResolverInternal.RotationResolverCallbackInternal() {
+
+ @Override
+ public void onSuccess(int result) {
+ synchronized (mLock) {
+ mLatencyTracker
+ .onActionEnd(ACTION_ROTATE_SCREEN_CAMERA_CHECK);
+ }
+ callbackInternal.onSuccess(result);
+ }
+
+ @Override
+ public void onFailure(int error) {
+ synchronized (mLock) {
+ mLatencyTracker
+ .onActionEnd(ACTION_ROTATE_SCREEN_CAMERA_CHECK);
+ }
+ callbackInternal.onFailure(error);
+ }
+ };
+ mCurrentRequest = new RemoteRotationResolverService.RotationRequest(wrapper,
request, cancellationSignalInternal);
cancellationSignalInternal.setOnCancelListener(() -> {
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java
index 457dc43..b1b537b 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java
@@ -304,6 +304,13 @@
mHandler.post(() -> mTimeZoneDetectorStrategy.suggestTelephonyTimeZone(timeZoneSuggestion));
}
+ boolean isTelephonyTimeZoneDetectionSupported() {
+ enforceManageTimeZoneDetectorPermission();
+
+ return ServiceConfigAccessor.getInstance(mContext)
+ .isTelephonyTimeZoneDetectionFeatureSupported();
+ }
+
boolean isGeoTimeZoneDetectionSupported() {
enforceManageTimeZoneDetectorPermission();
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorShellCommand.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorShellCommand.java
index 9899b448b..a4a46a3 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorShellCommand.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorShellCommand.java
@@ -18,6 +18,7 @@
import static android.app.timezonedetector.TimeZoneDetector.SHELL_COMMAND_IS_AUTO_DETECTION_ENABLED;
import static android.app.timezonedetector.TimeZoneDetector.SHELL_COMMAND_IS_GEO_DETECTION_ENABLED;
import static android.app.timezonedetector.TimeZoneDetector.SHELL_COMMAND_IS_GEO_DETECTION_SUPPORTED;
+import static android.app.timezonedetector.TimeZoneDetector.SHELL_COMMAND_IS_TELEPHONY_DETECTION_SUPPORTED;
import static android.app.timezonedetector.TimeZoneDetector.SHELL_COMMAND_SERVICE_NAME;
import static android.app.timezonedetector.TimeZoneDetector.SHELL_COMMAND_SET_AUTO_DETECTION_ENABLED;
import static android.app.timezonedetector.TimeZoneDetector.SHELL_COMMAND_SET_GEO_DETECTION_ENABLED;
@@ -61,6 +62,8 @@
return runIsAutoDetectionEnabled();
case SHELL_COMMAND_SET_AUTO_DETECTION_ENABLED:
return runSetAutoDetectionEnabled();
+ case SHELL_COMMAND_IS_TELEPHONY_DETECTION_SUPPORTED:
+ return runIsTelephonyDetectionSupported();
case SHELL_COMMAND_IS_GEO_DETECTION_SUPPORTED:
return runIsGeoDetectionSupported();
case SHELL_COMMAND_IS_GEO_DETECTION_ENABLED:
@@ -89,6 +92,13 @@
return 0;
}
+ private int runIsTelephonyDetectionSupported() {
+ final PrintWriter pw = getOutPrintWriter();
+ boolean enabled = mInterface.isTelephonyTimeZoneDetectionSupported();
+ pw.println(enabled);
+ return 0;
+ }
+
private int runIsGeoDetectionSupported() {
final PrintWriter pw = getOutPrintWriter();
boolean enabled = mInterface.isGeoTimeZoneDetectionSupported();
@@ -169,6 +179,9 @@
pw.printf(" Prints true/false according to the automatic time zone detection setting\n");
pw.printf(" %s true|false\n", SHELL_COMMAND_SET_AUTO_DETECTION_ENABLED);
pw.printf(" Sets the automatic time zone detection setting.\n");
+ pw.printf(" %s\n", SHELL_COMMAND_IS_TELEPHONY_DETECTION_SUPPORTED);
+ pw.printf(" Prints true/false according to whether telephony time zone detection is"
+ + " supported on this device.\n");
pw.printf(" %s\n", SHELL_COMMAND_IS_GEO_DETECTION_SUPPORTED);
pw.printf(" Prints true/false according to whether geolocation time zone detection is"
+ " supported on this device.\n");
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index 49170f3..aa63c52 100755
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -143,9 +143,9 @@
// ID of the current user.
@GuardedBy("mLock")
private int mCurrentUserId = UserHandle.USER_SYSTEM;
- // IDs of the running managed profiles. Their parent user ID should be mCurrentUserId.
+ // IDs of the running profiles. Their parent user ID should be mCurrentUserId.
@GuardedBy("mLock")
- private final Set<Integer> mRunningManagedProfile = new HashSet<>();
+ private final Set<Integer> mRunningProfiles = new HashSet<>();
// A map from user id to UserState.
@GuardedBy("mLock")
@@ -440,13 +440,13 @@
private void startUser(int userId) {
synchronized (mLock) {
- if (userId == mCurrentUserId || mRunningManagedProfile.contains(userId)) {
+ if (userId == mCurrentUserId || mRunningProfiles.contains(userId)) {
// user already started
return;
}
UserInfo userInfo = mUserManager.getUserInfo(userId);
UserInfo parentInfo = mUserManager.getProfileParent(userId);
- if (userInfo.isManagedProfile()
+ if (userInfo.isProfile()
&& parentInfo != null
&& parentInfo.id == mCurrentUserId) {
// only the children of the current user can be started in background
@@ -463,13 +463,13 @@
releaseSessionOfUserLocked(userId);
unbindServiceOfUserLocked(userId);
- mRunningManagedProfile.remove(userId);
+ mRunningProfiles.remove(userId);
}
private void startProfileLocked(int userId) {
buildTvInputListLocked(userId, null);
buildTvContentRatingSystemListLocked(userId);
- mRunningManagedProfile.add(userId);
+ mRunningProfiles.add(userId);
}
private void switchUser(int userId) {
@@ -478,16 +478,16 @@
return;
}
UserInfo userInfo = mUserManager.getUserInfo(userId);
- if (userInfo.isManagedProfile()) {
- Slog.w(TAG, "cannot switch to a managed profile!");
+ if (userInfo.isProfile()) {
+ Slog.w(TAG, "cannot switch to a profile!");
return;
}
- for (int runningId : mRunningManagedProfile) {
+ for (int runningId : mRunningProfiles) {
releaseSessionOfUserLocked(runningId);
unbindServiceOfUserLocked(runningId);
}
- mRunningManagedProfile.clear();
+ mRunningProfiles.clear();
releaseSessionOfUserLocked(mCurrentUserId);
unbindServiceOfUserLocked(mCurrentUserId);
@@ -630,7 +630,7 @@
userState.mCallbacks.kill();
userState.mainSessionToken = null;
- mRunningManagedProfile.remove(userId);
+ mRunningProfiles.remove(userId);
mUserStates.remove(userId);
if (userId == mCurrentUserId) {
@@ -729,7 +729,7 @@
}
boolean shouldBind;
- if (userId == mCurrentUserId || mRunningManagedProfile.contains(userId)) {
+ if (userId == mCurrentUserId || mRunningProfiles.contains(userId)) {
shouldBind = !serviceState.sessionTokens.isEmpty() || serviceState.isHardware;
} else {
// For a non-current user,
@@ -1400,9 +1400,9 @@
String uniqueSessionId = UUID.randomUUID().toString();
try {
synchronized (mLock) {
- if (userId != mCurrentUserId && !mRunningManagedProfile.contains(userId)
+ if (userId != mCurrentUserId && !mRunningProfiles.contains(userId)
&& !isRecordingSession) {
- // Only current user and its running managed profiles can create
+ // Only current user and its running profiles can create
// non-recording sessions.
// Let the client get onConnectionFailed callback for this case.
sendSessionTokenToClientLocked(client, inputId, null, null, seq);
diff --git a/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java b/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java
index 19fbdbd..5565ccb 100644
--- a/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java
+++ b/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java
@@ -145,7 +145,7 @@
*/
public void handleSubscriptionsChanged() {
final Map<ParcelUuid, Set<String>> privilegedPackages = new HashMap<>();
- final Map<Integer, ParcelUuid> newSubIdToGroupMap = new HashMap<>();
+ final Map<Integer, SubscriptionInfo> newSubIdToInfoMap = new HashMap<>();
final List<SubscriptionInfo> allSubs = mSubscriptionManager.getAllSubscriptionInfoList();
if (allSubs == null) {
@@ -160,7 +160,7 @@
}
// Build subId -> subGrp cache
- newSubIdToGroupMap.put(subInfo.getSubscriptionId(), subInfo.getGroupUuid());
+ newSubIdToInfoMap.put(subInfo.getSubscriptionId(), subInfo);
// Update subscription groups that are both ready, and active. For a group to be
// considered active, both of the following must be true:
@@ -186,7 +186,7 @@
}
final TelephonySubscriptionSnapshot newSnapshot =
- new TelephonySubscriptionSnapshot(newSubIdToGroupMap, privilegedPackages);
+ new TelephonySubscriptionSnapshot(newSubIdToInfoMap, privilegedPackages);
// If snapshot was meaningfully updated, fire the callback
if (!newSnapshot.equals(mCurrentSnapshot)) {
@@ -245,7 +245,7 @@
/** TelephonySubscriptionSnapshot is a class containing info about active subscriptions */
public static class TelephonySubscriptionSnapshot {
- private final Map<Integer, ParcelUuid> mSubIdToGroupMap;
+ private final Map<Integer, SubscriptionInfo> mSubIdToInfoMap;
private final Map<ParcelUuid, Set<String>> mPrivilegedPackages;
public static final TelephonySubscriptionSnapshot EMPTY_SNAPSHOT =
@@ -253,12 +253,12 @@
@VisibleForTesting(visibility = Visibility.PRIVATE)
TelephonySubscriptionSnapshot(
- @NonNull Map<Integer, ParcelUuid> subIdToGroupMap,
+ @NonNull Map<Integer, SubscriptionInfo> subIdToInfoMap,
@NonNull Map<ParcelUuid, Set<String>> privilegedPackages) {
- Objects.requireNonNull(subIdToGroupMap, "subIdToGroupMap was null");
+ Objects.requireNonNull(subIdToInfoMap, "subIdToInfoMap was null");
Objects.requireNonNull(privilegedPackages, "privilegedPackages was null");
- mSubIdToGroupMap = Collections.unmodifiableMap(subIdToGroupMap);
+ mSubIdToInfoMap = Collections.unmodifiableMap(subIdToInfoMap);
final Map<ParcelUuid, Set<String>> unmodifiableInnerSets = new ArrayMap<>();
for (Entry<ParcelUuid, Set<String>> entry : privilegedPackages.entrySet()) {
@@ -285,7 +285,9 @@
/** Returns the Subscription Group for a given subId. */
@Nullable
public ParcelUuid getGroupForSubId(int subId) {
- return mSubIdToGroupMap.get(subId);
+ return mSubIdToInfoMap.containsKey(subId)
+ ? mSubIdToInfoMap.get(subId).getGroupUuid()
+ : null;
}
/**
@@ -295,8 +297,8 @@
public Set<Integer> getAllSubIdsInGroup(ParcelUuid subGrp) {
final Set<Integer> subIds = new ArraySet<>();
- for (Entry<Integer, ParcelUuid> entry : mSubIdToGroupMap.entrySet()) {
- if (subGrp.equals(entry.getValue())) {
+ for (Entry<Integer, SubscriptionInfo> entry : mSubIdToInfoMap.entrySet()) {
+ if (subGrp.equals(entry.getValue().getGroupUuid())) {
subIds.add(entry.getKey());
}
}
@@ -304,9 +306,17 @@
return subIds;
}
+ /** Checks if the requested subscription is opportunistic */
+ @NonNull
+ public boolean isOpportunistic(int subId) {
+ return mSubIdToInfoMap.containsKey(subId)
+ ? mSubIdToInfoMap.get(subId).isOpportunistic()
+ : false;
+ }
+
@Override
public int hashCode() {
- return Objects.hash(mSubIdToGroupMap, mPrivilegedPackages);
+ return Objects.hash(mSubIdToInfoMap, mPrivilegedPackages);
}
@Override
@@ -317,7 +327,7 @@
final TelephonySubscriptionSnapshot other = (TelephonySubscriptionSnapshot) obj;
- return mSubIdToGroupMap.equals(other.mSubIdToGroupMap)
+ return mSubIdToInfoMap.equals(other.mSubIdToInfoMap)
&& mPrivilegedPackages.equals(other.mPrivilegedPackages);
}
@@ -326,7 +336,7 @@
pw.println("TelephonySubscriptionSnapshot:");
pw.increaseIndent();
- pw.println("mSubIdToGroupMap: " + mSubIdToGroupMap);
+ pw.println("mSubIdToInfoMap: " + mSubIdToInfoMap);
pw.println("mPrivilegedPackages: " + mPrivilegedPackages);
pw.decreaseIndent();
@@ -335,7 +345,7 @@
@Override
public String toString() {
return "TelephonySubscriptionSnapshot{ "
- + "mSubIdToGroupMap=" + mSubIdToGroupMap
+ + "mSubIdToInfoMap=" + mSubIdToInfoMap
+ ", mPrivilegedPackages=" + mPrivilegedPackages
+ " }";
}
diff --git a/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java b/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java
index 3bdeec0..fb4c623 100644
--- a/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java
+++ b/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java
@@ -16,6 +16,10 @@
package com.android.server.vcn;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+import static android.telephony.TelephonyCallback.ActiveDataSubscriptionIdListener;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.net.ConnectivityManager;
@@ -25,8 +29,16 @@
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.net.TelephonyNetworkSpecifier;
+import android.net.vcn.VcnManager;
import android.os.Handler;
+import android.os.HandlerExecutor;
import android.os.ParcelUuid;
+import android.os.PersistableBundle;
+import android.telephony.CarrierConfigManager;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyCallback;
+import android.telephony.TelephonyManager;
+import android.util.ArrayMap;
import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
@@ -35,9 +47,13 @@
import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.List;
+import java.util.Map;
import java.util.Objects;
import java.util.Set;
+import java.util.TreeSet;
/**
* Tracks a set of Networks underpinning a VcnGatewayConnection.
@@ -51,6 +67,45 @@
public class UnderlyingNetworkTracker {
@NonNull private static final String TAG = UnderlyingNetworkTracker.class.getSimpleName();
+ /**
+ * Minimum signal strength for a WiFi network to be eligible for switching to
+ *
+ * <p>A network that satisfies this is eligible to become the selected underlying network with
+ * no additional conditions
+ */
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ static final int WIFI_ENTRY_RSSI_THRESHOLD_DEFAULT = -70;
+
+ /**
+ * Minimum signal strength to continue using a WiFi network
+ *
+ * <p>A network that satisfies the conditions may ONLY continue to be used if it is already
+ * selected as the underlying network. A WiFi network satisfying this condition, but NOT the
+ * prospective-network RSSI threshold CANNOT be switched to.
+ */
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ static final int WIFI_EXIT_RSSI_THRESHOLD_DEFAULT = -74;
+
+ /** Priority for any cellular network for which the subscription is listed as opportunistic */
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ static final int PRIORITY_OPPORTUNISTIC_CELLULAR = 0;
+
+ /** Priority for any WiFi network which is in use, and satisfies the in-use RSSI threshold */
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ static final int PRIORITY_WIFI_IN_USE = 1;
+
+ /** Priority for any WiFi network which satisfies the prospective-network RSSI threshold */
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ static final int PRIORITY_WIFI_PROSPECTIVE = 2;
+
+ /** Priority for any standard macro cellular network */
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ static final int PRIORITY_MACRO_CELLULAR = 3;
+
+ /** Priority for any other networks (including unvalidated, etc) */
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ static final int PRIORITY_ANY = Integer.MAX_VALUE;
+
@NonNull private final VcnContext mVcnContext;
@NonNull private final ParcelUuid mSubscriptionGroup;
@NonNull private final Set<Integer> mRequiredUnderlyingNetworkCapabilities;
@@ -58,12 +113,17 @@
@NonNull private final Dependencies mDeps;
@NonNull private final Handler mHandler;
@NonNull private final ConnectivityManager mConnectivityManager;
+ @NonNull private final TelephonyCallback mActiveDataSubIdListener =
+ new VcnActiveDataSubscriptionIdListener();
@NonNull private final List<NetworkCallback> mCellBringupCallbacks = new ArrayList<>();
@Nullable private NetworkCallback mWifiBringupCallback;
- @Nullable private NetworkCallback mRouteSelectionCallback;
+ @Nullable private NetworkCallback mWifiEntryRssiThresholdCallback;
+ @Nullable private NetworkCallback mWifiExitRssiThresholdCallback;
+ @Nullable private UnderlyingNetworkListener mRouteSelectionCallback;
@NonNull private TelephonySubscriptionSnapshot mLastSnapshot;
+ @Nullable private PersistableBundle mCarrierConfig;
private boolean mIsQuitting = false;
@Nullable private UnderlyingNetworkRecord mCurrentRecord;
@@ -104,6 +164,30 @@
mHandler = new Handler(mVcnContext.getLooper());
mConnectivityManager = mVcnContext.getContext().getSystemService(ConnectivityManager.class);
+ mVcnContext
+ .getContext()
+ .getSystemService(TelephonyManager.class)
+ .registerTelephonyCallback(new HandlerExecutor(mHandler), mActiveDataSubIdListener);
+
+ // TODO: Listen for changes in carrier config that affect this.
+ for (int subId : mLastSnapshot.getAllSubIdsInGroup(mSubscriptionGroup)) {
+ PersistableBundle config =
+ mVcnContext
+ .getContext()
+ .getSystemService(CarrierConfigManager.class)
+ .getConfigForSubId(subId);
+
+ if (config != null) {
+ mCarrierConfig = config;
+
+ // Attempt to use (any) non-opportunistic subscription. If this subscription is
+ // opportunistic, continue and try to find a non-opportunistic subscription, using
+ // the opportunistic ones as a last resort.
+ if (!isOpportunistic(mLastSnapshot, Collections.singleton(subId))) {
+ break;
+ }
+ }
+ }
registerOrUpdateNetworkRequests();
}
@@ -111,16 +195,30 @@
private void registerOrUpdateNetworkRequests() {
NetworkCallback oldRouteSelectionCallback = mRouteSelectionCallback;
NetworkCallback oldWifiCallback = mWifiBringupCallback;
+ NetworkCallback oldWifiEntryRssiThresholdCallback = mWifiEntryRssiThresholdCallback;
+ NetworkCallback oldWifiExitRssiThresholdCallback = mWifiExitRssiThresholdCallback;
List<NetworkCallback> oldCellCallbacks = new ArrayList<>(mCellBringupCallbacks);
mCellBringupCallbacks.clear();
// Register new callbacks. Make-before-break; always register new callbacks before removal
// of old callbacks
if (!mIsQuitting) {
- mRouteSelectionCallback = new RouteSelectionCallback();
- mConnectivityManager.requestBackgroundNetwork(
+ mRouteSelectionCallback = new UnderlyingNetworkListener();
+ mConnectivityManager.registerNetworkCallback(
getRouteSelectionRequest(), mRouteSelectionCallback, mHandler);
+ mWifiEntryRssiThresholdCallback = new NetworkBringupCallback();
+ mConnectivityManager.registerNetworkCallback(
+ getWifiEntryRssiThresholdNetworkRequest(),
+ mWifiEntryRssiThresholdCallback,
+ mHandler);
+
+ mWifiExitRssiThresholdCallback = new NetworkBringupCallback();
+ mConnectivityManager.registerNetworkCallback(
+ getWifiExitRssiThresholdNetworkRequest(),
+ mWifiExitRssiThresholdCallback,
+ mHandler);
+
mWifiBringupCallback = new NetworkBringupCallback();
mConnectivityManager.requestBackgroundNetwork(
getWifiNetworkRequest(), mWifiBringupCallback, mHandler);
@@ -135,6 +233,8 @@
} else {
mRouteSelectionCallback = null;
mWifiBringupCallback = null;
+ mWifiEntryRssiThresholdCallback = null;
+ mWifiExitRssiThresholdCallback = null;
// mCellBringupCallbacks already cleared above.
}
@@ -145,6 +245,12 @@
if (oldWifiCallback != null) {
mConnectivityManager.unregisterNetworkCallback(oldWifiCallback);
}
+ if (oldWifiEntryRssiThresholdCallback != null) {
+ mConnectivityManager.unregisterNetworkCallback(oldWifiEntryRssiThresholdCallback);
+ }
+ if (oldWifiExitRssiThresholdCallback != null) {
+ mConnectivityManager.unregisterNetworkCallback(oldWifiExitRssiThresholdCallback);
+ }
for (NetworkCallback cellBringupCallback : oldCellCallbacks) {
mConnectivityManager.unregisterNetworkCallback(cellBringupCallback);
}
@@ -168,6 +274,8 @@
}
return getBaseNetworkRequestBuilder()
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED)
.setSubscriptionIds(mLastSnapshot.getAllSubIdsInGroup(mSubscriptionGroup))
.build();
}
@@ -189,6 +297,38 @@
}
/**
+ * Builds the WiFi entry threshold signal strength request
+ *
+ * <p>This request ensures that WiFi reports the crossing of the wifi entry RSSI threshold.
+ * Without this request, WiFi rate-limits, and reports signal strength changes at too slow a
+ * pace to effectively select a short-lived WiFi offload network.
+ */
+ private NetworkRequest getWifiEntryRssiThresholdNetworkRequest() {
+ return getBaseNetworkRequestBuilder()
+ .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+ .setSubscriptionIds(mLastSnapshot.getAllSubIdsInGroup(mSubscriptionGroup))
+ // Ensure wifi updates signal strengths when crossing this threshold.
+ .setSignalStrength(getWifiEntryRssiThreshold(mCarrierConfig))
+ .build();
+ }
+
+ /**
+ * Builds the WiFi exit threshold signal strength request
+ *
+ * <p>This request ensures that WiFi reports the crossing of the wifi exit RSSI threshold.
+ * Without this request, WiFi rate-limits, and reports signal strength changes at too slow a
+ * pace to effectively select away from a failing WiFi network.
+ */
+ private NetworkRequest getWifiExitRssiThresholdNetworkRequest() {
+ return getBaseNetworkRequestBuilder()
+ .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+ .setSubscriptionIds(mLastSnapshot.getAllSubIdsInGroup(mSubscriptionGroup))
+ // Ensure wifi updates signal strengths when crossing this threshold.
+ .setSignalStrength(getWifiExitRssiThreshold(mCarrierConfig))
+ .build();
+ }
+
+ /**
* Builds a Cellular bringup request for a given subId
*
* <p>This request is filed in order to ensure that the Telephony stack always has a
@@ -233,10 +373,18 @@
* reevaluate its NetworkBringupCallbacks. This may result in NetworkRequests being registered
* or unregistered if the subIds mapped to the this Tracker's SubscriptionGroup change.
*/
- public void updateSubscriptionSnapshot(@NonNull TelephonySubscriptionSnapshot snapshot) {
- Objects.requireNonNull(snapshot, "Missing snapshot");
+ public void updateSubscriptionSnapshot(@NonNull TelephonySubscriptionSnapshot newSnapshot) {
+ Objects.requireNonNull(newSnapshot, "Missing newSnapshot");
- mLastSnapshot = snapshot;
+ final TelephonySubscriptionSnapshot oldSnapshot = mLastSnapshot;
+ mLastSnapshot = newSnapshot;
+
+ // Only trigger re-registration if subIds in this group have changed
+ if (oldSnapshot
+ .getAllSubIdsInGroup(mSubscriptionGroup)
+ .equals(newSnapshot.getAllSubIdsInGroup(mSubscriptionGroup))) {
+ return;
+ }
registerOrUpdateNetworkRequests();
}
@@ -247,88 +395,43 @@
// Will unregister all existing callbacks, but not register new ones due to quitting flag.
registerOrUpdateNetworkRequests();
+
+ mVcnContext
+ .getContext()
+ .getSystemService(TelephonyManager.class)
+ .unregisterTelephonyCallback(mActiveDataSubIdListener);
}
- /** Returns whether the currently selected Network matches the given network. */
- private static boolean isSameNetwork(
- @Nullable UnderlyingNetworkRecord.Builder recordInProgress, @NonNull Network network) {
- return recordInProgress != null && recordInProgress.getNetwork().equals(network);
- }
+ private void reevaluateNetworks() {
+ TreeSet<UnderlyingNetworkRecord> sorted =
+ new TreeSet<>(
+ UnderlyingNetworkRecord.getComparator(
+ mSubscriptionGroup, mLastSnapshot, mCurrentRecord, mCarrierConfig));
+ sorted.addAll(mRouteSelectionCallback.getUnderlyingNetworks());
- /** Notify the Callback if a full UnderlyingNetworkRecord exists. */
- private void maybeNotifyCallback() {
- // Only forward this update if a complete record has been received
- if (!mRecordInProgress.isValid()) {
+ UnderlyingNetworkRecord candidate = sorted.isEmpty() ? null : sorted.first();
+ if (Objects.equals(mCurrentRecord, candidate)) {
return;
}
- // Only forward this update if the updated record differs form the current record
- UnderlyingNetworkRecord updatedRecord = mRecordInProgress.build();
- if (!updatedRecord.equals(mCurrentRecord)) {
- mCurrentRecord = updatedRecord;
-
- mCb.onSelectedUnderlyingNetworkChanged(mCurrentRecord);
- }
+ mCurrentRecord = candidate;
+ mCb.onSelectedUnderlyingNetworkChanged(mCurrentRecord);
}
- private void handleNetworkAvailable(@NonNull Network network) {
- mVcnContext.ensureRunningOnLooperThread();
-
- mRecordInProgress = new UnderlyingNetworkRecord.Builder(network);
- }
-
- private void handleNetworkLost(@NonNull Network network) {
- mVcnContext.ensureRunningOnLooperThread();
-
- if (!isSameNetwork(mRecordInProgress, network)) {
- Slog.wtf(TAG, "Non-underlying Network lost");
- return;
+ private static boolean isOpportunistic(
+ @NonNull TelephonySubscriptionSnapshot snapshot, Set<Integer> subIds) {
+ if (snapshot == null) {
+ Slog.wtf(TAG, "Got null snapshot");
+ return false;
}
- mRecordInProgress = null;
- mCurrentRecord = null;
- mCb.onSelectedUnderlyingNetworkChanged(null /* underlyingNetworkRecord */);
- }
-
- private void handleCapabilitiesChanged(
- @NonNull Network network, @NonNull NetworkCapabilities networkCapabilities) {
- mVcnContext.ensureRunningOnLooperThread();
-
- if (!isSameNetwork(mRecordInProgress, network)) {
- Slog.wtf(TAG, "Invalid update to NetworkCapabilities");
- return;
+ for (int subId : subIds) {
+ if (snapshot.isOpportunistic(subId)) {
+ return true;
+ }
}
- mRecordInProgress.setNetworkCapabilities(networkCapabilities);
-
- maybeNotifyCallback();
- }
-
- private void handlePropertiesChanged(
- @NonNull Network network, @NonNull LinkProperties linkProperties) {
- mVcnContext.ensureRunningOnLooperThread();
-
- if (!isSameNetwork(mRecordInProgress, network)) {
- Slog.wtf(TAG, "Invalid update to LinkProperties");
- return;
- }
-
- mRecordInProgress.setLinkProperties(linkProperties);
-
- maybeNotifyCallback();
- }
-
- private void handleNetworkBlocked(@NonNull Network network, boolean isBlocked) {
- mVcnContext.ensureRunningOnLooperThread();
-
- if (!isSameNetwork(mRecordInProgress, network)) {
- Slog.wtf(TAG, "Invalid update to isBlocked");
- return;
- }
-
- mRecordInProgress.setIsBlocked(isBlocked);
-
- maybeNotifyCallback();
+ return false;
}
/**
@@ -347,36 +450,104 @@
* truth.
*/
@VisibleForTesting
- class RouteSelectionCallback extends NetworkCallback {
+ class UnderlyingNetworkListener extends NetworkCallback {
+ private final Map<Network, UnderlyingNetworkRecord.Builder>
+ mUnderlyingNetworkRecordBuilders = new ArrayMap<>();
+
+ private List<UnderlyingNetworkRecord> getUnderlyingNetworks() {
+ final List<UnderlyingNetworkRecord> records = new ArrayList<>();
+
+ for (UnderlyingNetworkRecord.Builder builder :
+ mUnderlyingNetworkRecordBuilders.values()) {
+ if (builder.isValid()) {
+ records.add(builder.build());
+ }
+ }
+
+ return records;
+ }
+
@Override
public void onAvailable(@NonNull Network network) {
- handleNetworkAvailable(network);
+ mUnderlyingNetworkRecordBuilders.put(
+ network, new UnderlyingNetworkRecord.Builder(network));
}
@Override
public void onLost(@NonNull Network network) {
- handleNetworkLost(network);
+ mUnderlyingNetworkRecordBuilders.remove(network);
+
+ reevaluateNetworks();
}
@Override
public void onCapabilitiesChanged(
@NonNull Network network, @NonNull NetworkCapabilities networkCapabilities) {
- if (networkCapabilities.equals(mRecordInProgress.getNetworkCapabilities())) return;
- handleCapabilitiesChanged(network, networkCapabilities);
+ final UnderlyingNetworkRecord.Builder builder =
+ mUnderlyingNetworkRecordBuilders.get(network);
+ if (builder == null) {
+ Slog.wtf(TAG, "Got capabilities change for unknown key: " + network);
+ return;
+ }
+
+ builder.setNetworkCapabilities(networkCapabilities);
+ if (builder.isValid()) {
+ reevaluateNetworks();
+ }
}
@Override
public void onLinkPropertiesChanged(
@NonNull Network network, @NonNull LinkProperties linkProperties) {
- handlePropertiesChanged(network, linkProperties);
+ final UnderlyingNetworkRecord.Builder builder =
+ mUnderlyingNetworkRecordBuilders.get(network);
+ if (builder == null) {
+ Slog.wtf(TAG, "Got link properties change for unknown key: " + network);
+ return;
+ }
+
+ builder.setLinkProperties(linkProperties);
+ if (builder.isValid()) {
+ reevaluateNetworks();
+ }
}
@Override
public void onBlockedStatusChanged(@NonNull Network network, boolean isBlocked) {
- handleNetworkBlocked(network, isBlocked);
+ final UnderlyingNetworkRecord.Builder builder =
+ mUnderlyingNetworkRecordBuilders.get(network);
+ if (builder == null) {
+ Slog.wtf(TAG, "Got blocked status change for unknown key: " + network);
+ return;
+ }
+
+ builder.setIsBlocked(isBlocked);
+ if (builder.isValid()) {
+ reevaluateNetworks();
+ }
}
}
+ private static int getWifiEntryRssiThreshold(@Nullable PersistableBundle carrierConfig) {
+ if (carrierConfig != null) {
+ return carrierConfig.getInt(
+ VcnManager.VCN_NETWORK_SELECTION_WIFI_ENTRY_RSSI_THRESHOLD_KEY,
+ WIFI_ENTRY_RSSI_THRESHOLD_DEFAULT);
+ }
+
+ return WIFI_ENTRY_RSSI_THRESHOLD_DEFAULT;
+ }
+
+ private static int getWifiExitRssiThreshold(@Nullable PersistableBundle carrierConfig) {
+ if (carrierConfig != null) {
+ return carrierConfig.getInt(
+ VcnManager.VCN_NETWORK_SELECTION_WIFI_EXIT_RSSI_THRESHOLD_KEY,
+ WIFI_EXIT_RSSI_THRESHOLD_DEFAULT);
+ }
+
+ return WIFI_EXIT_RSSI_THRESHOLD_DEFAULT;
+ }
+
/** A record of a single underlying network, caching relevant fields. */
public static class UnderlyingNetworkRecord {
@NonNull public final Network network;
@@ -413,6 +584,89 @@
return Objects.hash(network, networkCapabilities, linkProperties, isBlocked);
}
+ /**
+ * Gives networks a priority class, based on the following priorities:
+ *
+ * <ol>
+ * <li>Opportunistic cellular
+ * <li>Carrier WiFi, signal strength >= WIFI_ENTRY_RSSI_THRESHOLD_DEFAULT
+ * <li>Carrier WiFi, active network + signal strength >= WIFI_EXIT_RSSI_THRESHOLD_DEFAULT
+ * <li>Macro cellular
+ * <li>Any others
+ * </ol>
+ */
+ private int calculatePriorityClass(
+ ParcelUuid subscriptionGroup,
+ TelephonySubscriptionSnapshot snapshot,
+ UnderlyingNetworkRecord currentlySelected,
+ PersistableBundle carrierConfig) {
+ final NetworkCapabilities caps = networkCapabilities;
+
+ // mRouteSelectionNetworkRequest requires a network be both VALIDATED and NOT_SUSPENDED
+
+ if (isBlocked) {
+ Slog.wtf(TAG, "Network blocked for System Server: " + network);
+ return PRIORITY_ANY;
+ }
+
+ if (caps.hasTransport(TRANSPORT_CELLULAR)
+ && isOpportunistic(snapshot, caps.getSubscriptionIds())) {
+ // If this carrier is the active data provider, ensure that opportunistic is only
+ // ever prioritized if it is also the active data subscription. This ensures that
+ // if an opportunistic subscription is still in the process of being switched to,
+ // or switched away from, the VCN does not attempt to continue using it against the
+ // decision made at the telephony layer. Failure to do so may result in the modem
+ // switching back and forth.
+ //
+ // Allow the following two cases:
+ // 1. Active subId is NOT in the group that this VCN is supporting
+ // 2. This opportunistic subscription is for the active subId
+ if (!snapshot.getAllSubIdsInGroup(subscriptionGroup)
+ .contains(SubscriptionManager.getActiveDataSubscriptionId())
+ || caps.getSubscriptionIds()
+ .contains(SubscriptionManager.getActiveDataSubscriptionId())) {
+ return PRIORITY_OPPORTUNISTIC_CELLULAR;
+ }
+ }
+
+ if (caps.hasTransport(TRANSPORT_WIFI)) {
+ if (caps.getSignalStrength() >= getWifiExitRssiThreshold(carrierConfig)
+ && currentlySelected != null
+ && network.equals(currentlySelected.network)) {
+ return PRIORITY_WIFI_IN_USE;
+ }
+
+ if (caps.getSignalStrength() >= getWifiEntryRssiThreshold(carrierConfig)) {
+ return PRIORITY_WIFI_PROSPECTIVE;
+ }
+ }
+
+ // Disallow opportunistic subscriptions from matching PRIORITY_MACRO_CELLULAR, as might
+ // be the case when Default Data SubId (CBRS) != Active Data SubId (MACRO), as might be
+ // the case if the Default Data SubId does not support certain services (eg voice
+ // calling)
+ if (caps.hasTransport(TRANSPORT_CELLULAR)
+ && !isOpportunistic(snapshot, caps.getSubscriptionIds())) {
+ return PRIORITY_MACRO_CELLULAR;
+ }
+
+ return PRIORITY_ANY;
+ }
+
+ private static Comparator<UnderlyingNetworkRecord> getComparator(
+ ParcelUuid subscriptionGroup,
+ TelephonySubscriptionSnapshot snapshot,
+ UnderlyingNetworkRecord currentlySelected,
+ PersistableBundle carrierConfig) {
+ return (left, right) -> {
+ return Integer.compare(
+ left.calculatePriorityClass(
+ subscriptionGroup, snapshot, currentlySelected, carrierConfig),
+ right.calculatePriorityClass(
+ subscriptionGroup, snapshot, currentlySelected, carrierConfig));
+ };
+ }
+
/** Dumps the state of this record for logging and debugging purposes. */
public void dump(IndentingPrintWriter pw) {
pw.println("UnderlyingNetworkRecord:");
@@ -434,6 +688,8 @@
boolean mIsBlocked;
boolean mWasIsBlockedSet;
+ @Nullable private UnderlyingNetworkRecord mCached;
+
private Builder(@NonNull Network network) {
mNetwork = network;
}
@@ -445,6 +701,7 @@
private void setNetworkCapabilities(@NonNull NetworkCapabilities networkCapabilities) {
mNetworkCapabilities = networkCapabilities;
+ mCached = null;
}
@Nullable
@@ -454,11 +711,13 @@
private void setLinkProperties(@NonNull LinkProperties linkProperties) {
mLinkProperties = linkProperties;
+ mCached = null;
}
private void setIsBlocked(boolean isBlocked) {
mIsBlocked = isBlocked;
mWasIsBlockedSet = true;
+ mCached = null;
}
private boolean isValid() {
@@ -466,12 +725,30 @@
}
private UnderlyingNetworkRecord build() {
- return new UnderlyingNetworkRecord(
- mNetwork, mNetworkCapabilities, mLinkProperties, mIsBlocked);
+ if (!isValid()) {
+ throw new IllegalArgumentException(
+ "Called build before UnderlyingNetworkRecord was valid");
+ }
+
+ if (mCached == null) {
+ mCached =
+ new UnderlyingNetworkRecord(
+ mNetwork, mNetworkCapabilities, mLinkProperties, mIsBlocked);
+ }
+
+ return mCached;
}
}
}
+ private class VcnActiveDataSubscriptionIdListener extends TelephonyCallback
+ implements ActiveDataSubscriptionIdListener {
+ @Override
+ public void onActiveDataSubscriptionIdChanged(int subId) {
+ reevaluateNetworks();
+ }
+ }
+
/** Callbacks for being notified of the changes in, or to the selected underlying network. */
public interface UnderlyingNetworkTrackerCallback {
/**
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
index 1ab402d..e1b7dd3 100644
--- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
@@ -76,6 +76,7 @@
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
+import android.content.pm.IncrementalStatesInfo;
import android.content.pm.dex.ArtManagerInternal;
import android.content.pm.dex.PackageOptimizationInfo;
import android.metrics.LogMaker;
@@ -84,6 +85,7 @@
import android.os.Looper;
import android.os.SystemClock;
import android.os.Trace;
+import android.os.incremental.IncrementalManager;
import android.util.ArrayMap;
import android.util.EventLog;
import android.util.Log;
@@ -948,6 +950,14 @@
builder.addTaggedData(PACKAGE_OPTIMIZATION_COMPILATION_FILTER,
packageOptimizationInfo.getCompilationFilter());
mMetricsLogger.write(builder);
+
+ // Incremental info
+ boolean isIncremental = false, isLoading = false;
+ final String codePath = info.applicationInfo.getCodePath();
+ if (codePath != null && IncrementalManager.isIncrementalPath(codePath)) {
+ isIncremental = true;
+ isLoading = isIncrementalLoading(info.packageName, info.userId);
+ }
FrameworkStatsLog.write(
FrameworkStatsLog.APP_START_OCCURRED,
info.applicationInfo.uid,
@@ -967,7 +977,10 @@
packageOptimizationInfo.getCompilationFilter(),
info.sourceType,
info.sourceEventDelayMs,
- isHibernating);
+ isHibernating,
+ isIncremental,
+ isLoading,
+ info.launchedActivityName.hashCode());
if (DEBUG_METRICS) {
Slog.i(TAG, String.format("APP_START_OCCURRED(%s, %s, %s, %s, %s)",
@@ -982,6 +995,12 @@
logAppStartMemoryStateCapture(info);
}
+ private boolean isIncrementalLoading(String packageName, int userId) {
+ final IncrementalStatesInfo info = mSupervisor.mService.getPackageManagerInternalLocked()
+ .getIncrementalStatesInfo(packageName, 0 /* filterCallingUid */, userId);
+ return info != null && info.isLoading();
+ }
+
private void logAppDisplayed(TransitionInfoSnapshot info) {
if (info.type != TYPE_TRANSITION_WARM_LAUNCH && info.type != TYPE_TRANSITION_COLD_LAUNCH) {
return;
@@ -1063,6 +1082,14 @@
mMetricsLogger.write(builder);
final PackageOptimizationInfo packageOptimizationInfo =
infoSnapshot.getPackageOptimizationInfo(getArtManagerInternal());
+ // Incremental info
+ boolean isIncremental = false, isLoading = false;
+ final String codePath = info.mLastLaunchedActivity.info.applicationInfo.getCodePath();
+ if (codePath != null && IncrementalManager.isIncrementalPath(codePath)) {
+ isIncremental = true;
+ isLoading = isIncrementalLoading(info.mLastLaunchedActivity.packageName,
+ info.mLastLaunchedActivity.mUserId);
+ }
FrameworkStatsLog.write(
FrameworkStatsLog.APP_START_FULLY_DRAWN,
info.mLastLaunchedActivity.info.applicationInfo.uid,
@@ -1076,7 +1103,10 @@
packageOptimizationInfo.getCompilationReason(),
packageOptimizationInfo.getCompilationFilter(),
info.mSourceType,
- info.mSourceEventDelayMs);
+ info.mSourceEventDelayMs,
+ isIncremental,
+ isLoading,
+ info.mLastLaunchedActivity.info.name.hashCode());
// Ends the trace started at the beginning of this function. This is located here to allow
// the trace slice to have a noticable duration.
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 667a4fa..65595a8 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -4213,6 +4213,7 @@
void clearAllDrawn() {
allDrawn = false;
+ mLastAllDrawn = false;
}
/**
@@ -6865,7 +6866,7 @@
}
// An activity in size compatibility mode may have override bounds which equals to its
// parent bounds, so the exact bounds should also be checked to allow IME window to attach
- // to the activity. See {@link DisplayContent#isImeAttachedToApp}.
+ // to the activity. See {@link DisplayContent#shouldImeAttachedToApp}.
final WindowContainer parent = getParent();
return parent == null || parent.getBounds().equals(overrideBounds);
}
@@ -7483,7 +7484,10 @@
if (mVisibleRequested) {
// It may toggle the UI for user to restart the size compatibility mode activity.
display.handleActivitySizeCompatModeIfNeeded(this);
- } else if (mCompatDisplayInsets != null) {
+ } else if (mCompatDisplayInsets != null && !visibleIgnoringKeyguard) {
+ // visibleIgnoringKeyguard is checked to avoid clearing mCompatDisplayInsets during
+ // displays change. Displays are turned off during the change so mVisibleRequested
+ // can be false.
// The override changes can only be obtained from display, because we don't have the
// difference of full configuration in each hierarchy.
final int displayChanges = display.getCurrentOverrideConfigurationChanges();
@@ -8240,6 +8244,11 @@
}
@Override
+ public boolean isAlwaysOnTop() {
+ return mTaskOverlay || super.isAlwaysOnTop();
+ }
+
+ @Override
boolean showToCurrentUser() {
return mShowForAllUsers || mWmService.isCurrentProfile(mUserId);
}
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 0d3c74e..7bc29f2 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -192,6 +192,7 @@
private boolean mKeepCurTransition;
private boolean mAvoidMoveToFront;
private boolean mFrozeTaskList;
+ private boolean mTransientLaunch;
// We must track when we deliver the new intent since multiple code paths invoke
// {@link #deliverNewIntent}. This is due to early returns in the code path. This flag is used
@@ -1792,7 +1793,7 @@
mTargetRootTask.moveToFront("startActivityInner");
}
mRootWindowContainer.resumeFocusedTasksTopActivities(
- mTargetRootTask, mStartActivity, mOptions);
+ mTargetRootTask, mStartActivity, mOptions, mTransientLaunch);
}
}
mRootWindowContainer.updateUserRootTask(mStartActivity.mUserId, mTargetRootTask);
@@ -2209,6 +2210,7 @@
mKeepCurTransition = false;
mAvoidMoveToFront = false;
mFrozeTaskList = false;
+ mTransientLaunch = false;
mVoiceSession = null;
mVoiceInteractor = null;
@@ -2311,6 +2313,7 @@
mDoResume = false;
mAvoidMoveToFront = true;
}
+ mTransientLaunch = mOptions.getTransientLaunch();
mTargetRootTask = Task.fromWindowContainerToken(mOptions.getLaunchRootTask());
}
@@ -2642,7 +2645,7 @@
}
if (mTargetRootTask.isFocusable()) {
mRootWindowContainer.resumeFocusedTasksTopActivities(mTargetRootTask, null,
- mOptions);
+ mOptions, mTransientLaunch);
} else {
mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
}
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index c6a66c5..37a9b80 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -835,7 +835,7 @@
final boolean forceResizable = Settings.Global.getInt(
resolver, DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES, 0) != 0;
final boolean devEnableNonResizableMultiWindow = Settings.Global.getInt(
- resolver, DEVELOPMENT_ENABLE_NON_RESIZABLE_MULTI_WINDOW, 1) != 0;
+ resolver, DEVELOPMENT_ENABLE_NON_RESIZABLE_MULTI_WINDOW, 0) != 0;
final int supportsNonResizableMultiWindow = mContext.getResources().getInteger(
com.android.internal.R.integer.config_supportsNonResizableMultiWindow);
final int respectsActivityMinWidthHeightMultiWindow = mContext.getResources().getInteger(
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index d5a7619..c1b287f 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -449,6 +449,19 @@
if (mRemoteAnimationController != null) {
mRemoteAnimationController.goodToGo(transit);
+ } else if ((isTaskOpenTransitOld(transit) || transit == TRANSIT_OLD_WALLPAPER_CLOSE)
+ && topOpeningAnim != null) {
+ if (mDisplayContent.getDisplayPolicy().shouldAttachNavBarToAppDuringTransition()
+ && mService.getRecentsAnimationController() == null) {
+ final NavBarFadeAnimationController controller =
+ new NavBarFadeAnimationController(mDisplayContent);
+ // For remote animation case, the nav bar fades out and in is controlled by the
+ // remote side. For non-remote animation case, we play the fade out/in animation
+ // here. We play the nav bar fade-out animation when the app transition animation
+ // starts and play the fade-in animation sequentially once the fade-out is finished.
+ controller.fadeOutAndInSequentially(topOpeningAnim.getDurationHint(),
+ null /* fadeOutParent */, topOpeningApp.getSurfaceControl());
+ }
}
return redoLayout;
}
diff --git a/services/core/java/com/android/server/wm/DisplayArea.java b/services/core/java/com/android/server/wm/DisplayArea.java
index 9855ea5..b24ab93 100644
--- a/services/core/java/com/android/server/wm/DisplayArea.java
+++ b/services/core/java/com/android/server/wm/DisplayArea.java
@@ -25,6 +25,9 @@
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
import static com.android.internal.util.Preconditions.checkState;
+import static com.android.server.wm.DisplayAreaProto.FEATURE_ID;
+import static com.android.server.wm.DisplayAreaProto.IS_ORGANIZED;
+import static com.android.server.wm.DisplayAreaProto.IS_ROOT_DISPLAY_AREA;
import static com.android.server.wm.DisplayAreaProto.IS_TASK_DISPLAY_AREA;
import static com.android.server.wm.DisplayAreaProto.NAME;
import static com.android.server.wm.DisplayAreaProto.WINDOW_CONTAINER;
@@ -273,6 +276,9 @@
super.dumpDebug(proto, WINDOW_CONTAINER, logLevel);
proto.write(NAME, mName);
proto.write(IS_TASK_DISPLAY_AREA, isTaskDisplayArea());
+ proto.write(IS_ROOT_DISPLAY_AREA, asRootDisplayArea() != null);
+ proto.write(FEATURE_ID, mFeatureId);
+ proto.write(IS_ORGANIZED, isOrganized());
proto.end(token);
}
@@ -515,7 +521,7 @@
return true;
}
- protected boolean isTaskDisplayArea() {
+ boolean isTaskDisplayArea() {
return false;
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 91f75e5..735fae3 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -1539,7 +1539,9 @@
// to cover the activity configuration change.
return false;
}
- if (r.mStartingData != null && r.mStartingData.hasImeSurface()) {
+ if ((r.mStartingData != null && r.mStartingData.hasImeSurface())
+ || (mInsetsStateController.getImeSourceProvider()
+ .getSource().getVisibleFrame() != null)) {
// Currently it is unknown that when will IME window be ready. Reject the case to
// avoid flickering by showing IME in inconsistent orientation.
return false;
@@ -2409,6 +2411,8 @@
mDisplayPolicy.onConfigurationChanged();
mPinnedTaskController.onPostDisplayConfigurationChanged();
}
+ // Update IME parent if needed.
+ updateImeParent();
if (lastOrientation != getConfiguration().orientation) {
getMetricsLogger().write(
@@ -2996,6 +3000,8 @@
// Hide the windows which are not significant in rotation animation. So that the windows
// don't need to block the unfreeze time.
if (screenRotationAnimation != null && screenRotationAnimation.hasScreenshot()
+ // Do not fade for freezing without rotation change.
+ && mDisplayRotation.getRotation() != getWindowConfiguration().getRotation()
&& mFadeRotationAnimationController == null) {
startFadeRotationAnimation(false /* shouldDebounce */);
}
@@ -3633,7 +3639,7 @@
return mImeInputTarget != null && !mImeInputTarget.inMultiWindowMode();
}
- boolean isImeAttachedToApp() {
+ boolean shouldImeAttachedToApp() {
return isImeControlledByApp()
&& mImeLayeringTarget != null
&& mImeLayeringTarget.mActivityRecord != null
@@ -3647,6 +3653,20 @@
}
/**
+ * Unlike {@link #shouldImeAttachedToApp()}, this method returns {@code @true} only when both
+ * the IME layering target is valid to attach the IME surface to the app, and the
+ * {@link #mInputMethodSurfaceParent} of the {@link ImeContainer} has actually attached to
+ * the app. (i.e. Even if {@link #shouldImeAttachedToApp()} returns {@code true}, calling this
+ * method will return {@code false} if the IME surface doesn't actually attach to the app.)
+ */
+ boolean isImeAttachedToApp() {
+ return shouldImeAttachedToApp()
+ && mInputMethodSurfaceParent != null
+ && mInputMethodSurfaceParent.isSameSurface(
+ mImeLayeringTarget.mActivityRecord.getSurfaceControl());
+ }
+
+ /**
* Finds the window which can host IME if IME target cannot host it.
* e.g. IME target cannot host IME when it's display has a parent display OR when display
* doesn't support IME/system decorations.
@@ -3774,7 +3794,7 @@
@VisibleForTesting
void attachAndShowImeScreenshotOnTarget() {
// No need to attach screenshot if the IME target not exists or screen is off.
- if (!isImeAttachedToApp() || !mWmService.mPolicy.isScreenOn()) {
+ if (!shouldImeAttachedToApp() || !mWmService.mPolicy.isScreenOn()) {
return;
}
@@ -3942,12 +3962,13 @@
// Attach it to app if the target is part of an app and such app is covering the entire
// screen. If it's not covering the entire screen the IME might extend beyond the apps
// bounds.
- if (allowAttachToApp && isImeAttachedToApp()) {
+ if (allowAttachToApp && shouldImeAttachedToApp()) {
return mImeLayeringTarget.mActivityRecord.getSurfaceControl();
}
// Otherwise, we just attach it to where the display area policy put it.
- return mImeWindowsContainer.getParent().getSurfaceControl();
+ return mImeWindowsContainer.getParent() != null
+ ? mImeWindowsContainer.getParent().getSurfaceControl() : null;
}
void setLayoutNeeded() {
@@ -4582,13 +4603,14 @@
return super.forAllWindows(callback, traverseTopToBottom);
}
- private boolean skipImeWindowsDuringTraversal(DisplayContent dc) {
+ private static boolean skipImeWindowsDuringTraversal(DisplayContent dc) {
// We skip IME windows so they're processed just above their target, except
// in split-screen mode where we process the IME containers above the docked divider.
// Note that this method check should align with {@link
// WindowState#applyImeWindowsIfNeeded} in case of any state mismatch.
- return dc.getImeTarget(IME_TARGET_LAYERING) != null
- && !dc.getDefaultTaskDisplayArea().isSplitScreenModeActivated();
+ return dc.mImeLayeringTarget != null
+ && (!dc.getDefaultTaskDisplayArea().isSplitScreenModeActivated()
+ || dc.mImeLayeringTarget.getTask() == null);
}
/** Like {@link #forAllWindows}, but ignores {@link #skipImeWindowsDuringTraversal} */
diff --git a/services/core/java/com/android/server/wm/DisplayHashController.java b/services/core/java/com/android/server/wm/DisplayHashController.java
index 94d81fb..0cf4379 100644
--- a/services/core/java/com/android/server/wm/DisplayHashController.java
+++ b/services/core/java/com/android/server/wm/DisplayHashController.java
@@ -16,8 +16,8 @@
package com.android.server.wm;
+import static android.service.displayhash.DisplayHashingService.EXTRA_INTERVAL_BETWEEN_REQUESTS;
import static android.service.displayhash.DisplayHashingService.EXTRA_VERIFIED_DISPLAY_HASH;
-import static android.service.displayhash.DisplayHashingService.SERVICE_META_DATA;
import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_INVALID_HASH_ALGORITHM;
import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_TOO_MANY_REQUESTS;
import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_UNKNOWN;
@@ -36,9 +36,6 @@
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.content.res.XmlResourceParser;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.RectF;
@@ -54,22 +51,15 @@
import android.service.displayhash.DisplayHashParams;
import android.service.displayhash.DisplayHashingService;
import android.service.displayhash.IDisplayHashingService;
-import android.util.AttributeSet;
import android.util.Size;
import android.util.Slog;
-import android.util.Xml;
import android.view.MagnificationSpec;
import android.view.SurfaceControl;
import android.view.displayhash.DisplayHash;
import android.view.displayhash.VerifiedDisplayHash;
-import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
@@ -114,25 +104,18 @@
private final Matrix mTmpMatrix = new Matrix();
private final RectF mTmpRectF = new RectF();
- /**
- * Lock used when retrieving xml metadata. Lock when retrieving the xml data the first time
- * since it will be cached after that. Check if {@link #mParsedXml} is set to determine if the
- * metadata needs to retrieved.
- */
- private final Object mParseXmlLock = new Object();
/**
- * Flag whether the xml metadata has been retrieved and parsed. Once this is set to true,
- * there's no need to request metadata again.
+ * Lock used for the cached {@link #mIntervalBetweenRequestMillis}
*/
- @GuardedBy("mParseXmlLock")
- private boolean mParsedXml;
+ private final Object mIntervalBetweenRequestsLock = new Object();
/**
* Specified duration between requests to generate a display hash in milliseconds. Requests
* faster than this delay will be throttled.
*/
- private int mDurationBetweenRequestMillis = 0;
+ @GuardedBy("mDurationBetweenRequestsLock")
+ private int mIntervalBetweenRequestMillis = -1;
/**
* The last time an app requested to generate a display hash in System time.
@@ -203,8 +186,8 @@
return true;
}
- int mDurationBetweenRequestsMs = getDurationBetweenRequestMillis();
- if (currentTime - mLastRequestTimeMs < mDurationBetweenRequestsMs) {
+ int mIntervalBetweenRequestsMs = getIntervalBetweenRequestMillis();
+ if (currentTime - mLastRequestTimeMs < mIntervalBetweenRequestsMs) {
return false;
}
@@ -356,61 +339,25 @@
}
}
- private int getDurationBetweenRequestMillis() {
- if (!parseXmlProperties()) {
- return 0;
- }
- return mDurationBetweenRequestMillis;
- }
-
- private boolean parseXmlProperties() {
- // We have a separate lock for the xml parsing since it doesn't need to make the
- // request through the service connection. Instead, we have a lock to ensure we can
- // properly cache the xml metadata so we don't need to call into the ExtServices
- // process for each request.
- synchronized (mParseXmlLock) {
- if (mParsedXml) {
- return true;
+ private int getIntervalBetweenRequestMillis() {
+ // We have a separate lock for the hashing params to ensure we can properly cache the
+ // hashing params so we don't need to call into the ExtServices process for each request.
+ synchronized (mIntervalBetweenRequestsLock) {
+ if (mIntervalBetweenRequestMillis != -1) {
+ return mIntervalBetweenRequestMillis;
}
- final ServiceInfo serviceInfo = getServiceInfo();
- if (serviceInfo == null) return false;
-
- final PackageManager pm = mContext.getPackageManager();
-
- XmlResourceParser parser;
- parser = serviceInfo.loadXmlMetaData(pm, SERVICE_META_DATA);
- if (parser == null) {
- return false;
- }
-
- Resources res;
- try {
- res = pm.getResourcesForApplication(serviceInfo.applicationInfo);
- } catch (PackageManager.NameNotFoundException e) {
- return false;
- }
-
- AttributeSet attrs = Xml.asAttributeSet(parser);
-
- int type;
- while (true) {
+ final SyncCommand syncCommand = new SyncCommand();
+ Bundle results = syncCommand.run((service, remoteCallback) -> {
try {
- if (!((type = parser.next()) != XmlPullParser.END_DOCUMENT
- && type != XmlPullParser.START_TAG)) {
- break;
- }
- } catch (XmlPullParserException | IOException e) {
- return false;
+ service.getIntervalBetweenRequestsMillis(remoteCallback);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to invoke getDisplayHashAlgorithms command", e);
}
- }
+ });
- TypedArray sa = res.obtainAttributes(attrs, R.styleable.DisplayHashingService);
- mDurationBetweenRequestMillis = sa.getInt(
- R.styleable.DisplayHashingService_durationBetweenRequestsMillis, 0);
- sa.recycle();
- mParsedXml = true;
- return true;
+ mIntervalBetweenRequestMillis = results.getInt(EXTRA_INTERVAL_BETWEEN_REQUESTS, 0);
+ return mIntervalBetweenRequestMillis;
}
}
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 37e15c7..30151c3 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -373,7 +373,6 @@
* when the navigation bar mode is changed.
*/
private boolean mShouldAttachNavBarToAppDuringTransition;
- private NavBarFadeAnimationController mNavBarFadeAnimationController;
// -------- PolicyHandler --------
private static final int MSG_REQUEST_TRANSIENT_BARS = 2;
@@ -1088,7 +1087,6 @@
break;
case TYPE_NAVIGATION_BAR:
mNavigationBar = win;
- updateNavBarFadeController();
mDisplayContent.setInsetProvider(ITYPE_NAVIGATION_BAR, win,
(displayFrames, windowState, inOutFrame) -> {
@@ -1234,7 +1232,6 @@
mDisplayContent.setInsetProvider(ITYPE_STATUS_BAR, null, null);
} else if (mNavigationBar == win || mNavigationBarAlt == win) {
mNavigationBar = null;
- updateNavBarFadeController();
mNavigationBarAlt = null;
mDisplayContent.setInsetProvider(ITYPE_NAVIGATION_BAR, null, null);
} else if (mNotificationShade == win) {
@@ -2060,7 +2057,6 @@
res.getBoolean(R.bool.config_attachNavBarToAppDuringTransition);
if (mShouldAttachNavBarToAppDuringTransition != shouldAttach) {
mShouldAttachNavBarToAppDuringTransition = shouldAttach;
- updateNavBarFadeController();
}
}
@@ -3062,19 +3058,4 @@
boolean shouldAttachNavBarToAppDuringTransition() {
return mShouldAttachNavBarToAppDuringTransition && mNavigationBar != null;
}
-
- @Nullable NavBarFadeAnimationController getNavBarFadeAnimationController() {
- return mNavBarFadeAnimationController;
- }
-
- private void updateNavBarFadeController() {
- if (shouldAttachNavBarToAppDuringTransition()) {
- if (mNavBarFadeAnimationController == null) {
- mNavBarFadeAnimationController =
- new NavBarFadeAnimationController(mDisplayContent);
- }
- } else {
- mNavBarFadeAnimationController = null;
- }
- }
}
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index 0e73d79..2c969ab 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -186,6 +186,10 @@
@Surface.Rotation
private int mUserRotation = Surface.ROTATION_0;
+ private static final int CAMERA_ROTATION_DISABLED = 0;
+ private static final int CAMERA_ROTATION_ENABLED = 1;
+ private int mCameraRotationMode = CAMERA_ROTATION_DISABLED;
+
/**
* Flag that indicates this is a display that may run better when fixed to user rotation.
*/
@@ -1462,6 +1466,14 @@
if (shouldUpdateOrientationListener) {
updateOrientationListenerLw(); // Enable or disable the orientation listener.
}
+
+ final int cameraRotationMode = Settings.Secure.getIntForUser(resolver,
+ Settings.Secure.CAMERA_AUTOROTATE, 0,
+ UserHandle.USER_CURRENT);
+ if (mCameraRotationMode != cameraRotationMode) {
+ mCameraRotationMode = cameraRotationMode;
+ shouldUpdateRotation = true;
+ }
}
return shouldUpdateRotation;
@@ -1491,6 +1503,7 @@
pw.print(prefix + " mUserRotationMode="
+ WindowManagerPolicy.userRotationModeToString(mUserRotationMode));
pw.print(" mUserRotation=" + Surface.rotationToString(mUserRotation));
+ pw.print(" mCameraRotationMode=" + mCameraRotationMode);
pw.println(" mAllowAllRotations=" + allowAllRotationsToString(mAllowAllRotations));
pw.print(prefix + " mDemoHdmiRotation=" + Surface.rotationToString(mDemoHdmiRotation));
@@ -1539,6 +1552,13 @@
}
}
+ @Override
+ public boolean isRotationResolverEnabled() {
+ return mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE
+ && mCameraRotationMode == CAMERA_ROTATION_ENABLED
+ && !mService.mPowerManager.isPowerSaveMode();
+ }
+
@Override
public void onProposedRotationChanged(int rotation) {
@@ -1582,6 +1602,10 @@
resolver.registerContentObserver(Settings.System.getUriFor(
Settings.System.USER_ROTATION), false, this,
UserHandle.USER_ALL);
+ resolver.registerContentObserver(
+ Settings.Secure.getUriFor(Settings.Secure.CAMERA_AUTOROTATE), false, this,
+ UserHandle.USER_ALL);
+
updateSettings();
}
diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java
index fd4bbd7..c674cb85 100644
--- a/services/core/java/com/android/server/wm/DragState.java
+++ b/services/core/java/com/android/server/wm/DragState.java
@@ -16,6 +16,9 @@
package com.android.server.wm;
+import static android.content.ClipDescription.MIMETYPE_APPLICATION_ACTIVITY;
+import static android.content.ClipDescription.MIMETYPE_APPLICATION_SHORTCUT;
+import static android.content.ClipDescription.MIMETYPE_APPLICATION_TASK;
import static android.os.InputConstants.DEFAULT_DISPATCHING_TIMEOUT_MILLIS;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_INTERCEPT_GLOBAL_DRAG_AND_DROP;
@@ -441,8 +444,9 @@
Slog.d(TAG_WM, "broadcasting DRAG_STARTED at (" + touchX + ", " + touchY + ")");
}
+ final boolean containsAppExtras = containsApplicationExtras(mDataDescription);
mService.mRoot.forAllWindows(w -> {
- sendDragStartedLocked(w, touchX, touchY, mDataDescription, mData);
+ sendDragStartedLocked(w, touchX, touchY, containsAppExtras);
}, false /* traverseTopToBottom */);
}
@@ -455,9 +459,9 @@
* process, so it's safe for the caller to call recycle() on the event afterwards.
*/
private void sendDragStartedLocked(WindowState newWin, float touchX, float touchY,
- ClipDescription desc, ClipData data) {
+ boolean containsAppExtras) {
final boolean interceptsGlobalDrag = targetInterceptsGlobalDrag(newWin);
- if (mDragInProgress && isValidDropTarget(newWin, interceptsGlobalDrag)) {
+ if (mDragInProgress && isValidDropTarget(newWin, containsAppExtras, interceptsGlobalDrag)) {
DragEvent event = obtainDragEvent(DragEvent.ACTION_DRAG_STARTED, touchX, touchY,
interceptsGlobalDrag, false /* includeDragSurface */,
null /* dragAndDropPermission */);
@@ -476,16 +480,35 @@
}
}
- private boolean isValidDropTarget(WindowState targetWin, boolean interceptsGlobalDrag) {
+ /**
+ * Returns true if this is a drag of an application mime type.
+ */
+ private boolean containsApplicationExtras(ClipDescription desc) {
+ if (desc == null) {
+ return false;
+ }
+ return desc.hasMimeType(MIMETYPE_APPLICATION_ACTIVITY)
+ || desc.hasMimeType(MIMETYPE_APPLICATION_SHORTCUT)
+ || desc.hasMimeType(MIMETYPE_APPLICATION_TASK);
+ }
+
+ private boolean isValidDropTarget(WindowState targetWin, boolean containsAppExtras,
+ boolean interceptsGlobalDrag) {
if (targetWin == null) {
return false;
}
+ final boolean isLocalWindow = mLocalWin == targetWin.mClient.asBinder();
+ if (!isLocalWindow && !interceptsGlobalDrag && containsAppExtras) {
+ // App-drags can only go to local windows or windows that can intercept global drag, and
+ // not to other app windows
+ return false;
+ }
if (!targetWin.isPotentialDragTarget(interceptsGlobalDrag)) {
return false;
}
if ((mFlags & View.DRAG_FLAG_GLOBAL) == 0 || !targetWindowSupportsGlobalDrag(targetWin)) {
// Drag is limited to the current window.
- if (mLocalWin != targetWin.mClient.asBinder()) {
+ if (!isLocalWindow) {
return false;
}
}
@@ -522,7 +545,8 @@
if (DEBUG_DRAG) {
Slog.d(TAG_WM, "need to send DRAG_STARTED to new window " + newWin);
}
- sendDragStartedLocked(newWin, mCurrentX, mCurrentY, mDataDescription, mData);
+ sendDragStartedLocked(newWin, mCurrentX, mCurrentY,
+ containsApplicationExtras(mDataDescription));
}
}
diff --git a/services/core/java/com/android/server/wm/FadeAnimationController.java b/services/core/java/com/android/server/wm/FadeAnimationController.java
index 17d20ae..2f3ad40 100644
--- a/services/core/java/com/android/server/wm/FadeAnimationController.java
+++ b/services/core/java/com/android/server/wm/FadeAnimationController.java
@@ -37,7 +37,7 @@
*/
public class FadeAnimationController {
protected final Context mContext;
- private final ArrayMap<WindowToken, Runnable> mDeferredFinishCallbacks = new ArrayMap<>();
+ protected final ArrayMap<WindowToken, Runnable> mDeferredFinishCallbacks = new ArrayMap<>();
public FadeAnimationController(DisplayContent displayContent) {
mContext = displayContent.mWmService.mContext;
@@ -69,17 +69,11 @@
return;
}
- final Animation animation = show ? getFadeInAnimation() : getFadeOutAnimation();
- if (animation == null) {
+ final FadeAnimationAdapter animationAdapter = createAdapter(show, windowToken);
+ if (animationAdapter == null) {
return;
}
- final LocalAnimationAdapter.AnimationSpec windowAnimationSpec =
- createAnimationSpec(animation);
-
- final FadeAnimationAdapter animationAdapter = new FadeAnimationAdapter(
- windowAnimationSpec, windowToken.getSurfaceAnimationRunner(), show, windowToken);
-
// We deferred the end of the animation when hiding the token, so we need to end it now that
// it's shown again.
final SurfaceAnimator.OnAnimationFinishedCallback finishedCallback = show ? (t, r) -> {
@@ -92,7 +86,21 @@
show /* hidden */, animationType, finishedCallback);
}
- private LocalAnimationAdapter.AnimationSpec createAnimationSpec(@NonNull Animation animation) {
+ protected FadeAnimationAdapter createAdapter(boolean show, WindowToken windowToken) {
+ final Animation animation = show ? getFadeInAnimation() : getFadeOutAnimation();
+ if (animation == null) {
+ return null;
+ }
+
+ final LocalAnimationAdapter.AnimationSpec windowAnimationSpec =
+ createAnimationSpec(animation);
+
+ return new FadeAnimationAdapter(
+ windowAnimationSpec, windowToken.getSurfaceAnimationRunner(), show, windowToken);
+ }
+
+ protected LocalAnimationAdapter.AnimationSpec createAnimationSpec(
+ @NonNull Animation animation) {
return new LocalAnimationAdapter.AnimationSpec() {
final Transformation mTransformation = new Transformation();
@@ -130,8 +138,8 @@
};
}
- private class FadeAnimationAdapter extends LocalAnimationAdapter {
- private final boolean mShow;
+ protected class FadeAnimationAdapter extends LocalAnimationAdapter {
+ protected final boolean mShow;
private final WindowToken mToken;
FadeAnimationAdapter(AnimationSpec windowAnimationSpec,
diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java
index cda3fda..c387d33 100644
--- a/services/core/java/com/android/server/wm/InsetsPolicy.java
+++ b/services/core/java/com/android/server/wm/InsetsPolicy.java
@@ -22,6 +22,7 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.view.InsetsController.ANIMATION_TYPE_HIDE;
import static android.view.InsetsController.ANIMATION_TYPE_SHOW;
+import static android.view.InsetsState.ITYPE_IME;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
import static android.view.SyncRtSurfaceTransactionApplier.applyParams;
@@ -207,7 +208,8 @@
*/
InsetsState getInsetsForWindow(WindowState target) {
final InsetsState originalState = mStateController.getInsetsForWindow(target);
- return adjustVisibilityForTransientTypes(originalState);
+ final InsetsState state = adjustVisibilityForTransientTypes(originalState);
+ return target.mIsImWindow ? adjustVisibilityForIme(state, state == originalState) : state;
}
/**
@@ -237,6 +239,20 @@
return state;
}
+ // Navigation bar insets is always visible to IME.
+ private static InsetsState adjustVisibilityForIme(InsetsState originalState,
+ boolean copyState) {
+ final InsetsSource originalNavSource = originalState.peekSource(ITYPE_NAVIGATION_BAR);
+ if (originalNavSource != null && !originalNavSource.isVisible()) {
+ final InsetsState state = copyState ? new InsetsState(originalState) : originalState;
+ final InsetsSource navSource = new InsetsSource(originalNavSource);
+ navSource.setVisible(true);
+ state.addSource(navSource);
+ return state;
+ }
+ return originalState;
+ }
+
void onInsetsModified(InsetsControlTarget caller) {
mStateController.onInsetsModified(caller);
checkAbortTransient(caller);
@@ -245,17 +261,21 @@
/**
* Called when a control target modified the insets state. If the target set a insets source to
- * visible while it is shown transiently, we need to abort the transient state.
+ * visible while it is shown transiently, we need to abort the transient state. While IME is
+ * requested visible, we also need to abort the transient state of navigation bar if it is shown
+ * transiently.
*
* @param caller who changed the insets state.
*/
private void checkAbortTransient(InsetsControlTarget caller) {
if (mShowingTransientTypes.size() != 0) {
- IntArray abortTypes = new IntArray();
+ final IntArray abortTypes = new IntArray();
+ final boolean imeRequestedVisible = caller.getRequestedVisibility(ITYPE_IME);
for (int i = mShowingTransientTypes.size() - 1; i >= 0; i--) {
final @InternalInsetsType int type = mShowingTransientTypes.get(i);
- if (mStateController.isFakeTarget(type, caller)
- && caller.getRequestedVisibility(type)) {
+ if ((mStateController.isFakeTarget(type, caller)
+ && caller.getRequestedVisibility(type))
+ || (type == ITYPE_NAVIGATION_BAR && imeRequestedVisible)) {
mShowingTransientTypes.remove(i);
abortTypes.add(type);
}
@@ -330,6 +350,11 @@
private @Nullable InsetsControlTarget getNavControlTarget(@Nullable WindowState focusedWin,
boolean forceShowsSystemBarsForWindowingMode) {
+ final WindowState imeWin = mDisplayContent.mInputMethodWindow;
+ if (imeWin != null && imeWin.isVisible()) {
+ // Force showing navigation bar while IME is visible.
+ return null;
+ }
if (mShowingTransientTypes.indexOf(ITYPE_NAVIGATION_BAR) != -1) {
return mDummyControlTarget;
}
diff --git a/services/core/java/com/android/server/wm/NavBarFadeAnimationController.java b/services/core/java/com/android/server/wm/NavBarFadeAnimationController.java
index 30861eb..e50dc51 100644
--- a/services/core/java/com/android/server/wm/NavBarFadeAnimationController.java
+++ b/services/core/java/com/android/server/wm/NavBarFadeAnimationController.java
@@ -18,6 +18,7 @@
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION;
+import android.view.SurfaceControl;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.Interpolator;
@@ -35,12 +36,17 @@
private static final Interpolator FADE_OUT_INTERPOLATOR =
new PathInterpolator(0.2f, 0f, 1f, 1f);
+ private DisplayContent mDisplayContent;
private final WindowState mNavigationBar;
private Animation mFadeInAnimation;
private Animation mFadeOutAnimation;
+ private SurfaceControl mFadeInParent;
+ private SurfaceControl mFadeOutParent;
+ private boolean mPlaySequentially = false;
public NavBarFadeAnimationController(DisplayContent displayContent) {
super(displayContent);
+ mDisplayContent = displayContent;
mNavigationBar = displayContent.getDisplayPolicy().getNavigationBar();
mFadeInAnimation = new AlphaAnimation(0f, 1f);
mFadeInAnimation.setDuration(FADE_IN_DURATION);
@@ -61,12 +67,103 @@
return mFadeOutAnimation;
}
+ @Override
+ protected FadeAnimationAdapter createAdapter(boolean show, WindowToken windowToken) {
+ final Animation animation = show ? getFadeInAnimation() : getFadeOutAnimation();
+ if (animation == null) {
+ return null;
+ }
+
+ final LocalAnimationAdapter.AnimationSpec windowAnimationSpec =
+ createAnimationSpec(animation);
+ return new NavFadeAnimationAdapter(
+ windowAnimationSpec, windowToken.getSurfaceAnimationRunner(), show, windowToken,
+ show ? mFadeInParent : mFadeOutParent);
+ }
+
/**
* Run the fade-in/out animation for the navigation bar.
*
* @param show true for fade-in, otherwise for fade-out.
*/
public void fadeWindowToken(boolean show) {
- fadeWindowToken(show, mNavigationBar.mToken, ANIMATION_TYPE_APP_TRANSITION);
+ final FadeRotationAnimationController controller =
+ mDisplayContent.getFadeRotationAnimationController();
+ final Runnable fadeAnim = () -> fadeWindowToken(show, mNavigationBar.mToken,
+ ANIMATION_TYPE_APP_TRANSITION);
+ if (controller == null) {
+ fadeAnim.run();
+ } else if (!controller.isTargetToken(mNavigationBar.mToken)) {
+ // If fade rotation animation is running and the nav bar is not controlled by it:
+ // - For fade-in animation, defer the animation until fade rotation animation finishes.
+ // - For fade-out animation, just play the animation.
+ if (show) {
+ controller.setOnShowRunnable(fadeAnim);
+ } else {
+ fadeAnim.run();
+ }
+ } else {
+ // If fade rotation animation is running and controlling the nav bar, make sure we empty
+ // the mDeferredFinishCallbacks and defer the runnable until fade rotation animation
+ // finishes.
+ final Runnable runnable = mDeferredFinishCallbacks.remove(mNavigationBar.mToken);
+ if (runnable != null) {
+ controller.setOnShowRunnable(runnable);
+ }
+ }
+ }
+
+ void fadeOutAndInSequentially(long totalDuration, SurfaceControl fadeOutParent,
+ SurfaceControl fadeInParent) {
+ mPlaySequentially = true;
+ if (totalDuration > 0) {
+ // The animation duration of each animation varies so we set the fade-out duration to
+ // 1/3 of the total app transition duration and set the fade-in duration to 2/3 of it.
+ final long fadeInDuration = totalDuration * 2L / 3L;
+ mFadeOutAnimation.setDuration(totalDuration - fadeInDuration);
+ mFadeInAnimation.setDuration(fadeInDuration);
+ }
+ mFadeOutParent = fadeOutParent;
+ mFadeInParent = fadeInParent;
+ fadeWindowToken(false);
+ }
+
+ /**
+ * The animation adapter that is capable of playing fade-out and fade-in sequentially and
+ * reparenting the navigation bar to a specified SurfaceControl when fade animation starts.
+ */
+ protected class NavFadeAnimationAdapter extends FadeAnimationAdapter {
+ private SurfaceControl mParent;
+
+ NavFadeAnimationAdapter(AnimationSpec windowAnimationSpec,
+ SurfaceAnimationRunner surfaceAnimationRunner, boolean show,
+ WindowToken token, SurfaceControl parent) {
+ super(windowAnimationSpec, surfaceAnimationRunner, show, token);
+ mParent = parent;
+ }
+
+ @Override
+ public void startAnimation(SurfaceControl animationLeash, SurfaceControl.Transaction t,
+ int type, SurfaceAnimator.OnAnimationFinishedCallback finishCallback) {
+ super.startAnimation(animationLeash, t, type, finishCallback);
+ if (mParent != null && mParent.isValid()) {
+ t.reparent(animationLeash, mParent);
+ // Place the nav bar on top of anything else (e.g. ime and starting window) in the
+ // parent.
+ t.setLayer(animationLeash, Integer.MAX_VALUE);
+ }
+ }
+
+ @Override
+ public boolean shouldDeferAnimationFinish(Runnable endDeferFinishCallback) {
+ if (mPlaySequentially) {
+ if (!mShow) {
+ fadeWindowToken(true);
+ }
+ return false;
+ } else {
+ return super.shouldDeferAnimationFinish(endDeferFinishCallback);
+ }
+ }
}
}
diff --git a/services/core/java/com/android/server/wm/RecentTasks.java b/services/core/java/com/android/server/wm/RecentTasks.java
index 9f9ac3e..455f568 100644
--- a/services/core/java/com/android/server/wm/RecentTasks.java
+++ b/services/core/java/com/android/server/wm/RecentTasks.java
@@ -1888,7 +1888,12 @@
*/
ActivityManager.RecentTaskInfo createRecentTaskInfo(Task tr, boolean stripExtras) {
final ActivityManager.RecentTaskInfo rti = new ActivityManager.RecentTaskInfo();
- tr.fillTaskInfo(rti, stripExtras);
+ // If the recent Task is detached, we consider it will be re-attached to the default
+ // TaskDisplayArea because we currently only support recent overview in the default TDA.
+ final TaskDisplayArea tda = tr.isAttached()
+ ? tr.getDisplayArea()
+ : mService.mRootWindowContainer.getDefaultTaskDisplayArea();
+ tr.fillTaskInfo(rti, stripExtras, tda);
// Fill in some deprecated values.
rti.id = rti.isRunning ? rti.taskId : INVALID_TASK_ID;
rti.persistentId = rti.taskId;
@@ -1900,7 +1905,7 @@
final Task childTask = tr.getChildAt(i).asTask();
if (childTask != null && childTask.isOrganized()) {
final ActivityManager.RecentTaskInfo cti = new ActivityManager.RecentTaskInfo();
- childTask.fillTaskInfo(cti);
+ childTask.fillTaskInfo(cti, true /* stripExtras */, tda);
rti.childrenTaskInfos.add(cti);
}
}
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index dec6460..b44a980 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -231,7 +231,8 @@
@Override
public void setFinishTaskTransaction(int taskId,
- PictureInPictureSurfaceTransaction finishTransaction) {
+ PictureInPictureSurfaceTransaction finishTransaction,
+ SurfaceControl overlay) {
ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS,
"setFinishTaskTransaction(%d): transaction=%s", taskId, finishTransaction);
final long token = Binder.clearCallingIdentity();
@@ -241,6 +242,7 @@
final TaskAnimationAdapter taskAdapter = mPendingAnimations.get(i);
if (taskAdapter.mTask.mTaskId == taskId) {
taskAdapter.mFinishTransaction = finishTransaction;
+ taskAdapter.mFinishOverlay = overlay;
break;
}
}
@@ -289,12 +291,6 @@
}
}
if (!behindSystemBars) {
- // Make sure to update the correct IME parent in case that the IME parent
- // may be computed as display layer when re-layout window happens during
- // rotation but there is intermediate state that the bounds of task and
- // the IME target's activity is not the same during rotating.
- mDisplayContent.updateImeParent();
-
// Hiding IME if IME window is not attached to app.
// Since some windowing mode is not proper to snapshot Task with IME window
// while the app transitioning to the next task (e.g. split-screen mode)
@@ -518,7 +514,6 @@
void removeAnimation(TaskAnimationAdapter taskAdapter) {
ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS,
"removeAnimation(%d)", taskAdapter.mTask.mTaskId);
- taskAdapter.mTask.setCanAffectSystemUiFlags(true);
taskAdapter.mCapturedFinishCallback.onAnimationFinished(taskAdapter.mLastAnimationType,
taskAdapter);
mPendingAnimations.remove(taskAdapter);
@@ -633,6 +628,7 @@
return;
}
mNavigationBarAttachedToApp = true;
+ navWindow.mToken.cancelAnimation();
final SurfaceControl.Transaction t = navWindow.mToken.getPendingTransaction();
final SurfaceControl navSurfaceControl = navWindow.mToken.getSurfaceControl();
if (shouldTranslateNavBar) {
@@ -653,7 +649,8 @@
}
}
- private void restoreNavigationBarFromApp(boolean animate) {
+ @VisibleForTesting
+ void restoreNavigationBarFromApp(boolean animate) {
if (!mNavigationBarAttachedToApp) {
return;
}
@@ -676,23 +673,9 @@
t.setLayer(navToken.getSurfaceControl(), navToken.getLastLayer());
if (animate) {
- final NavBarFadeAnimationController navBarFadeAnimationController =
- mDisplayContent.getDisplayPolicy().getNavBarFadeAnimationController();
- final Runnable fadeInAnim = () -> {
- // Reparent the SurfaceControl of nav bar token back.
- t.reparent(navToken.getSurfaceControl(), parent.getSurfaceControl());
- // Run fade-in animation to show navigation bar back to bottom of the display.
- if (navBarFadeAnimationController != null) {
- navBarFadeAnimationController.fadeWindowToken(true);
- }
- };
- final FadeRotationAnimationController fadeRotationAnimationController =
- mDisplayContent.getFadeRotationAnimationController();
- if (fadeRotationAnimationController != null) {
- fadeRotationAnimationController.setOnShowRunnable(fadeInAnim);
- } else {
- fadeInAnim.run();
- }
+ final NavBarFadeAnimationController controller =
+ new NavBarFadeAnimationController(mDisplayContent);
+ controller.fadeWindowToken(true);
} else {
// Reparent the SurfaceControl of nav bar token back.
t.reparent(navToken.getSurfaceControl(), parent.getSurfaceControl());
@@ -1106,6 +1089,8 @@
private final Rect mLocalBounds = new Rect();
// The final surface transaction when animation is finished.
private PictureInPictureSurfaceTransaction mFinishTransaction;
+ // An overlay used to mask the content as an app goes into PIP
+ private SurfaceControl mFinishOverlay;
TaskAnimationAdapter(Task task, boolean isRecentTaskInvisible) {
mTask = task;
@@ -1143,20 +1128,38 @@
void onCleanup() {
if (mFinishTransaction != null) {
final Transaction pendingTransaction = mTask.getPendingTransaction();
+
+ // Reparent the overlay
+ if (mFinishOverlay != null) {
+ pendingTransaction.reparent(mFinishOverlay, mTask.mSurfaceControl);
+ }
+
+ // Transfer the transform from the leash to the task
PictureInPictureSurfaceTransaction.apply(mFinishTransaction,
mTask.mSurfaceControl, pendingTransaction);
- mTask.setLastRecentsAnimationTransaction(mFinishTransaction);
+ mTask.setLastRecentsAnimationTransaction(mFinishTransaction, mFinishOverlay);
if (mDisplayContent.isFixedRotationLaunchingApp(mTargetActivityRecord)) {
// The transaction is needed for position when rotating the display.
mDisplayContent.mPinnedTaskController.setEnterPipTransaction(
mFinishTransaction);
}
mFinishTransaction = null;
+ mFinishOverlay = null;
pendingTransaction.apply();
+
+ // In the case where we are transferring the transform to the task in preparation
+ // for entering PIP, we disable the task being able to affect sysui flags otherwise
+ // it may cause a flash
+ if (mTask.getActivityType() != mTargetActivityType) {
+ mTask.setCanAffectSystemUiFlags(false);
+ }
} else if (!mTask.isAttached()) {
// Apply the task's pending transaction in case it is detached and its transaction
// is not reachable.
mTask.getPendingTransaction().apply();
+
+ // Reset whether this task can affect the sysui flags
+ mTask.setCanAffectSystemUiFlags(true);
}
}
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 0879ddd..ea80b8b 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -2139,7 +2139,8 @@
// Move the last recents animation transaction from original task to the new one.
if (task.mLastRecentsAnimationTransaction != null) {
rootTask.setLastRecentsAnimationTransaction(
- task.mLastRecentsAnimationTransaction);
+ task.mLastRecentsAnimationTransaction,
+ task.mLastRecentsAnimationOverlay);
task.clearLastRecentsAnimationTransaction();
}
@@ -2292,7 +2293,13 @@
boolean resumeFocusedTasksTopActivities(
Task targetRootTask, ActivityRecord target, ActivityOptions targetOptions) {
+ return resumeFocusedTasksTopActivities(targetRootTask, target, targetOptions,
+ false /* deferPause */);
+ }
+ boolean resumeFocusedTasksTopActivities(
+ Task targetRootTask, ActivityRecord target, ActivityOptions targetOptions,
+ boolean deferPause) {
if (!mTaskSupervisor.readyToResume()) {
return false;
}
@@ -2300,7 +2307,8 @@
boolean result = false;
if (targetRootTask != null && (targetRootTask.isTopRootTaskInDisplayArea()
|| getTopDisplayFocusedRootTask() == targetRootTask)) {
- result = targetRootTask.resumeTopActivityUncheckedLocked(target, targetOptions);
+ result = targetRootTask.resumeTopActivityUncheckedLocked(target, targetOptions,
+ deferPause);
}
for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
index d67a0d3..50749a9 100644
--- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -253,7 +253,16 @@
ProtoLog.i(WM_SHOW_SURFACE_ALLOC,
" FREEZE %s: CREATE", mScreenshotLayer);
- setRotation(t, realOriginalRotation);
+ if (originalRotation == realOriginalRotation) {
+ setRotation(t, realOriginalRotation);
+ } else {
+ // If the given original rotation is different from real original display rotation,
+ // this is playing non-zero degree rotation animation without display rotation change,
+ // so the snapshot doesn't need to be transformed.
+ mCurRotation = realOriginalRotation;
+ mSnapshotInitialMatrix.reset();
+ setRotationTransform(t, mSnapshotInitialMatrix);
+ }
t.apply();
}
diff --git a/services/core/java/com/android/server/wm/SurfaceAnimator.java b/services/core/java/com/android/server/wm/SurfaceAnimator.java
index ba18893..3c6c23b 100644
--- a/services/core/java/com/android/server/wm/SurfaceAnimator.java
+++ b/services/core/java/com/android/server/wm/SurfaceAnimator.java
@@ -520,7 +520,7 @@
/**
* Converts {@link AnimationType} to String.
*/
- private static String animationTypeToString(@AnimationType int type) {
+ static String animationTypeToString(@AnimationType int type) {
switch (type) {
case ANIMATION_TYPE_NONE: return "none";
case ANIMATION_TYPE_APP_TRANSITION: return "app_transition";
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 80a68f5..796e267 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -202,7 +202,6 @@
import android.service.voice.IVoiceInteractionSession;
import android.util.ArraySet;
import android.util.DisplayMetrics;
-import android.util.Log;
import android.util.Slog;
import android.util.TypedXmlPullParser;
import android.util.TypedXmlSerializer;
@@ -483,6 +482,9 @@
// Do not forget to reset this after reparenting.
// TODO: remove this once the recents animation is moved to the Shell
PictureInPictureSurfaceTransaction mLastRecentsAnimationTransaction;
+ // The content overlay to be applied with mLastRecentsAnimationTransaction
+ // TODO: remove this once the recents animation is moved to the Shell
+ SurfaceControl mLastRecentsAnimationOverlay;
static final int LAYER_RANK_INVISIBLE = -1;
// Ranking (from top) of this task among all visible tasks. (-1 means it's not visible)
@@ -1077,25 +1079,6 @@
}
/**
- * Convenience method to reparent a task to the top or bottom position of the root task, with
- * an option to skip scheduling the picture-in-picture mode change.
- */
- boolean reparent(Task preferredRootTask, boolean toTop,
- @ReparentMoveRootTaskMode int moveRootTaskMode, boolean animate, boolean deferResume,
- boolean schedulePictureInPictureModeChange, String reason) {
- return reparent(preferredRootTask, toTop ? MAX_VALUE : 0, moveRootTaskMode, animate,
- deferResume, schedulePictureInPictureModeChange, reason);
- }
-
- /** Convenience method to reparent a task to a specific position of the root task. */
- boolean reparent(Task preferredRootTask, int position,
- @ReparentMoveRootTaskMode int moveRootTaskMode, boolean animate, boolean deferResume,
- String reason) {
- return reparent(preferredRootTask, position, moveRootTaskMode, animate, deferResume,
- true /* schedulePictureInPictureModeChange */, reason);
- }
-
- /**
* Reparents the task into a preferred root task, creating it if necessary.
*
* @param preferredRootTask the target root task to move this task
@@ -2020,6 +2003,8 @@
return false;
}
if (tda == null) {
+ Slog.w(TAG_TASKS, "Can't find TaskDisplayArea to determine support for multi"
+ + " window. Task id=" + mTaskId + " attached=" + isAttached());
return false;
}
@@ -2954,20 +2939,6 @@
return bounds;
}
- /** Updates the task's bounds and override configuration to match what is expected for the
- * input root task. */
- void updateOverrideConfigurationForRootTask(Task inRootTask) {
- final Task rootTask = getRootTask();
-
- if (rootTask != null && rootTask == inRootTask) {
- return;
- }
-
- if (!inRootTask.inFreeformWindowingMode()) {
- setBounds(inRootTask.getRequestedOverrideBounds());
- }
- }
-
/** Returns the bounds that should be used to launch this task. */
Rect getLaunchBounds() {
final Task rootTask = getRootTask();
@@ -3181,11 +3152,14 @@
// Figure-out min/max possible position depending on if child can show for current user.
int minPosition = (canShowChild) ? computeMinUserPosition(0, size) : 0;
- int maxPosition = (canShowChild) ? size : computeMaxUserPosition(size - 1);
+ int maxPosition = (canShowChild) ? size - 1 : computeMaxUserPosition(size - 1);
+ if (!hasChild(wc)) {
+ // Increase the maxPosition because children size will grow once wc is added.
+ ++maxPosition;
+ }
// Factor in always-on-top children in max possible position.
if (!wc.isAlwaysOnTop()) {
-
// We want to place all non-always-on-top containers below always-on-top ones.
while (maxPosition > minPosition) {
if (!mChildren.get(maxPosition - 1).isAlwaysOnTop()) break;
@@ -4077,10 +4051,17 @@
fillTaskInfo(info, true /* stripExtras */);
}
+ void fillTaskInfo(TaskInfo info, boolean stripExtras) {
+ fillTaskInfo(info, stripExtras, getDisplayArea());
+ }
+
/**
* Fills in a {@link TaskInfo} with information from this task.
+ *
+ * @param tda consider whether this Task can be put in multi window as it will be attached to
+ * the give {@link TaskDisplayArea}.
*/
- void fillTaskInfo(TaskInfo info, boolean stripExtras) {
+ void fillTaskInfo(TaskInfo info, boolean stripExtras, @Nullable TaskDisplayArea tda) {
getNumRunningActivities(mReuseActivitiesReport);
info.userId = isLeafTask() ? mUserId : mCurrentUser;
info.taskId = mTaskId;
@@ -4105,8 +4086,8 @@
info.numActivities = mReuseActivitiesReport.numActivities;
info.lastActiveTime = lastActiveTime;
info.taskDescription = new ActivityManager.TaskDescription(getTaskDescription());
- info.supportsSplitScreenMultiWindow = supportsSplitScreenWindowingMode();
- info.supportsMultiWindow = supportsMultiWindow();
+ info.supportsSplitScreenMultiWindow = supportsSplitScreenWindowingModeInDisplayArea(tda);
+ info.supportsMultiWindow = supportsMultiWindowInDisplayArea(tda);
info.configuration.setTo(getConfiguration());
// Update to the task's current activity type and windowing mode which may differ from the
// window configuration
@@ -5417,6 +5398,10 @@
: WINDOWING_MODE_FULLSCREEN;
}
if (currentMode == WINDOWING_MODE_PINNED) {
+ // In the case that we've disabled affecting the SysUI flags as a part of seamlessly
+ // transferring the transform on the leash to the task, reset this state once we've
+ // actually entered pip
+ setCanAffectSystemUiFlags(true);
mRootWindowContainer.notifyActivityPipModeChanged(null);
}
if (likelyResolvedMode == WINDOWING_MODE_PINNED
@@ -6018,16 +6003,6 @@
return inPinnedWindowingMode();
}
- // TODO(NOW!)
- /**
- * Returns {@code true} if this is the top-most split-screen-primary or
- * split-screen-secondary root task, {@code false} otherwise.
- */
- boolean isTopSplitScreenRootTask() {
- return inSplitScreenWindowingMode()
- && this == getDisplayArea().getTopRootTaskInWindowingMode(getWindowingMode());
- }
-
void checkTranslucentActivityWaiting(ActivityRecord top) {
if (mTranslucentActivityWaiting != top) {
mUndrawnActivitiesBelowTopTranslucent.clear();
@@ -6103,6 +6078,7 @@
* @param prev The previously resumed activity, for when in the process
* of pausing; can be null to call from elsewhere.
* @param options Activity options.
+ * @param deferPause When {@code true}, this will not pause back tasks.
*
* @return Returns true if something is being resumed, or false if
* nothing happened.
@@ -6113,7 +6089,8 @@
* right activity for the current system state.
*/
@GuardedBy("mService")
- boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
+ boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options,
+ boolean deferPause) {
if (mInResumeTopActivity) {
// Don't even start recursing.
return false;
@@ -6126,7 +6103,7 @@
if (isLeafTask()) {
if (isFocusableAndVisible()) {
- someActivityResumed = resumeTopActivityInnerLocked(prev, options);
+ someActivityResumed = resumeTopActivityInnerLocked(prev, options, deferPause);
}
} else {
int idx = mChildren.size() - 1;
@@ -6139,7 +6116,8 @@
break;
}
- someActivityResumed |= child.resumeTopActivityUncheckedLocked(prev, options);
+ someActivityResumed |= child.resumeTopActivityUncheckedLocked(prev, options,
+ deferPause);
// Doing so in order to prevent IndexOOB since hierarchy might changes while
// resuming activities, for example dismissing split-screen while starting
// non-resizeable activity.
@@ -6167,8 +6145,15 @@
return someActivityResumed;
}
+ /** @see #resumeTopActivityUncheckedLocked(ActivityRecord, ActivityOptions, boolean) */
@GuardedBy("mService")
- private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
+ boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
+ return resumeTopActivityUncheckedLocked(prev, options, false /* skipPause */);
+ }
+
+ @GuardedBy("mService")
+ private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options,
+ boolean deferPause) {
if (!mAtmService.isBooting() && !mAtmService.isBooted()) {
// Not ready yet!
return false;
@@ -6229,9 +6214,7 @@
// If we are sleeping, and there is no resumed activity, and the top activity is paused,
// well that is the state we want.
- if (shouldSleepOrShutDownActivities()
- && mLastPausedActivity == next
- && mRootWindowContainer.allPausedActivitiesComplete()) {
+ if (mLastPausedActivity == next && shouldSleepOrShutDownActivities()) {
// Make sure we have executed any pending transitions, since there
// should be nothing left to do at this point.
executeAppTransition(options);
@@ -6255,14 +6238,6 @@
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming " + next);
- // If we are currently pausing an activity, then don't do anything until that is done.
- if (!mRootWindowContainer.allPausedActivitiesComplete()) {
- ProtoLog.v(WM_DEBUG_STATES,
- "resumeTopActivityLocked: Skip resume: some activity pausing.");
-
- return false;
- }
-
mTaskSupervisor.setLaunchSource(next.info.applicationInfo.uid);
ActivityRecord lastResumed = null;
@@ -6274,7 +6249,7 @@
lastResumed = lastFocusedRootTask.getResumedActivity();
}
- boolean pausing = taskDisplayArea.pauseBackTasks(next);
+ boolean pausing = !deferPause && taskDisplayArea.pauseBackTasks(next);
if (mResumedActivity != null) {
ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivityLocked: Pausing %s", mResumedActivity);
pausing |= startPausingLocked(false /* uiSleeping */, next,
@@ -7275,21 +7250,6 @@
task.setBounds(displayedBounds);
}
- /**
- * Until we can break this "set task bounds to same as root task bounds" behavior, this
- * basically resizes both root task and task bounds to the same bounds.
- */
- private void setTaskBounds(Rect bounds) {
- final PooledConsumer c = PooledLambda.obtainConsumer(Task::setTaskBoundsInner,
- PooledLambda.__(Task.class), bounds);
- forAllLeafTasks(c, true /* traverseTopToBottom */);
- c.recycle();
- }
-
- private static void setTaskBoundsInner(Task task, Rect bounds) {
- task.setBounds(task.isResizeable() ? bounds : null);
- }
-
boolean willActivityBeVisible(IBinder token) {
final ActivityRecord r = ActivityRecord.forTokenLocked(token);
if (r == null) {
@@ -7549,51 +7509,6 @@
}
}
- void positionChildAt(Task task, int position) {
- if (task.getRootTask() != this) {
- throw new IllegalArgumentException("AS.positionChildAt: task=" + task
- + " is not a child of root task=" + this + " current parent="
- + task.getRootTask());
- }
-
- task.updateOverrideConfigurationForRootTask(this);
-
- final ActivityRecord topRunningActivity = task.topRunningActivityLocked();
- final boolean wasResumed = topRunningActivity == task.mResumedActivity;
-
- boolean toTop = position >= getChildCount();
- boolean includingParents = toTop || getDisplayArea().getNextFocusableRootTask(this,
- true /* ignoreCurrent */) == null;
- if (WindowManagerDebugConfig.DEBUG_ROOT_TASK) {
- Slog.i(TAG_WM, "positionChildAt: positioning task=" + task + " at " + position);
- }
- positionChildAt(position, task, includingParents);
- getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
-
-
- // TODO: Investigate if this random code is really needed.
- if (task.voiceSession != null) {
- try {
- task.voiceSession.taskStarted(task.intent, task.mTaskId);
- } catch (RemoteException e) {
- }
- }
-
- if (wasResumed) {
- if (mResumedActivity != null) {
- Log.wtf(TAG, "mResumedActivity was already set when moving mResumedActivity from"
- + " other root task to this task mResumedActivity=" + mResumedActivity
- + " other mResumedActivity=" + topRunningActivity);
- }
- topRunningActivity.setState(RESUMED, "positionChildAt");
- }
-
- // The task might have already been running and its visibility needs to be synchronized with
- // the visibility of the root task / windows.
- ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
- mRootWindowContainer.resumeFocusedTasksTopActivities();
- }
-
public void setAlwaysOnTop(boolean alwaysOnTop) {
// {@link #isAwaysonTop} overrides the original behavior which also evaluates if this
// task is force hidden, so super.isAlwaysOnTop() is used here to see whether the
@@ -7730,22 +7645,28 @@
reparent(newParent, onTop ? POSITION_TOP : POSITION_BOTTOM);
}
- void setLastRecentsAnimationTransaction(
- @NonNull PictureInPictureSurfaceTransaction transaction) {
+ void setLastRecentsAnimationTransaction(@NonNull PictureInPictureSurfaceTransaction transaction,
+ @Nullable SurfaceControl overlay) {
mLastRecentsAnimationTransaction = new PictureInPictureSurfaceTransaction(transaction);
+ mLastRecentsAnimationOverlay = overlay;
}
void clearLastRecentsAnimationTransaction() {
mLastRecentsAnimationTransaction = null;
+ mLastRecentsAnimationOverlay = null;
// reset also the transform introduced by mLastRecentsAnimationTransaction
getPendingTransaction().setMatrix(mSurfaceControl, Matrix.IDENTITY_MATRIX, new float[9]);
}
void maybeApplyLastRecentsAnimationTransaction() {
if (mLastRecentsAnimationTransaction != null) {
+ if (mLastRecentsAnimationOverlay != null) {
+ getPendingTransaction().reparent(mLastRecentsAnimationOverlay, mSurfaceControl);
+ }
PictureInPictureSurfaceTransaction.apply(mLastRecentsAnimationTransaction,
mSurfaceControl, getPendingTransaction());
mLastRecentsAnimationTransaction = null;
+ mLastRecentsAnimationOverlay = null;
}
}
@@ -7864,8 +7785,8 @@
// Do not sleep activities in this root task if we're marked as focused and the keyguard
// is in the process of going away.
- if (isFocusedRootTaskOnDisplay()
- && mTaskSupervisor.getKeyguardController().isKeyguardGoingAway()
+ if (mTaskSupervisor.getKeyguardController().isKeyguardGoingAway()
+ && isFocusedRootTaskOnDisplay()
// Avoid resuming activities on secondary displays since we don't want bubble
// activities to be resumed while bubble is still collapsed.
// TODO(b/113840485): Having keyguard going away state for secondary displays.
@@ -7880,14 +7801,6 @@
return shouldSleepActivities() || mAtmService.mShuttingDown;
}
- /** Bounds of the root task without adjusting for other factors in the system like visibility
- * of root docked task.
- * Most callers should be using {@link ConfigurationContainer#getRequestedOverrideBounds} a
- * it takes into consideration other system factors. */
- void getRawBounds(Rect out) {
- out.set(getRawBounds());
- }
-
private Rect getRawBounds() {
return super.getBounds();
}
diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java
index ccfdb8c..ae90a7d 100644
--- a/services/core/java/com/android/server/wm/TaskDisplayArea.java
+++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java
@@ -2131,7 +2131,7 @@
}
@Override
- protected boolean isTaskDisplayArea() {
+ boolean isTaskDisplayArea() {
return true;
}
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index d49b6a0..9ffb2b1 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -425,7 +425,7 @@
final WindowState imeWindow = task.getDisplayContent().mInputMethodWindow;
// Exclude IME window snapshot when IME isn't proper to attach to app.
final boolean excludeIme = imeWindow != null && imeWindow.getSurfaceControl() != null
- && !task.getDisplayContent().isImeAttachedToApp();
+ && !task.getDisplayContent().shouldImeAttachedToApp();
final WindowState navWindow =
task.getDisplayContent().getDisplayPolicy().getNavigationBar();
// If config_attachNavBarToAppDuringTransition is true, the nav bar will be reparent to the
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index ab5e498..8bee862 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -106,6 +106,7 @@
import static com.android.server.wm.DisplayContent.IME_TARGET_CONTROL;
import static com.android.server.wm.DisplayContent.IME_TARGET_INPUT;
import static com.android.server.wm.DisplayContent.IME_TARGET_LAYERING;
+import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_ALL;
import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
@@ -947,7 +948,7 @@
void updateDevEnableNonResizableMultiWindow() {
ContentResolver resolver = mContext.getContentResolver();
final boolean devEnableNonResizableMultiWindow = Settings.Global.getInt(resolver,
- DEVELOPMENT_ENABLE_NON_RESIZABLE_MULTI_WINDOW, 1) != 0;
+ DEVELOPMENT_ENABLE_NON_RESIZABLE_MULTI_WINDOW, 0) != 0;
mAtmService.mDevEnableNonResizableMultiWindow = devEnableNonResizableMultiWindow;
}
@@ -8090,8 +8091,13 @@
// This could prevent if there is no container animation, we still have to apply the
// pending transaction and exit waiting.
mAnimator.mNotifyWhenNoAnimation = true;
- while ((mAnimator.isAnimationScheduled()
- || mRoot.isAnimating(TRANSITION | CHILDREN)) && timeoutRemaining > 0) {
+ WindowContainer animatingContainer = null;
+ while (mAnimator.isAnimationScheduled() || timeoutRemaining > 0) {
+ animatingContainer = mRoot.getAnimatingContainer(TRANSITION | CHILDREN,
+ ANIMATION_TYPE_ALL);
+ if (animatingContainer == null) {
+ break;
+ }
long startTime = System.currentTimeMillis();
try {
mGlobalLock.wait(timeoutRemaining);
@@ -8101,9 +8107,13 @@
}
mAnimator.mNotifyWhenNoAnimation = false;
- if (mAnimator.isAnimationScheduled()
- || mRoot.isAnimating(TRANSITION | CHILDREN)) {
- Slog.w(TAG, "Timed out waiting for animations to complete.");
+ if (mAnimator.isAnimationScheduled() || animatingContainer != null) {
+ Slog.w(TAG, "Timed out waiting for animations to complete,"
+ + " animatingContainer=" + animatingContainer
+ + " animationType=" + SurfaceAnimator.animationTypeToString(
+ animatingContainer != null
+ ? animatingContainer.mSurfaceAnimator.getAnimationType()
+ : SurfaceAnimator.ANIMATION_TYPE_NONE));
}
}
}
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index b7ad820..a82a478 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -16,7 +16,6 @@
package com.android.server.wm;
-import static android.Manifest.permission.READ_FRAME_BUFFER;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_CHILDREN_TASKS_REPARENT;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_LAUNCH_TASK;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REORDER;
@@ -37,8 +36,6 @@
import android.app.WindowConfiguration;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
-import android.graphics.GraphicBuffer;
-import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.os.Binder;
import android.os.Bundle;
@@ -53,7 +50,6 @@
import android.window.ITransitionPlayer;
import android.window.IWindowContainerTransactionCallback;
import android.window.IWindowOrganizerController;
-import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
import com.android.internal.annotations.VisibleForTesting;
@@ -787,44 +783,6 @@
}
@Override
- public boolean takeScreenshot(WindowContainerToken token, SurfaceControl outSurfaceControl) {
- mService.mAmInternal.enforceCallingPermission(READ_FRAME_BUFFER, "takeScreenshot()");
- final WindowContainer wc = WindowContainer.fromBinder(token.asBinder());
- if (wc == null) {
- throw new RuntimeException("Invalid token in screenshot transaction");
- }
-
- final Rect bounds = new Rect();
- wc.getBounds(bounds);
- bounds.offsetTo(0, 0);
- SurfaceControl.ScreenshotHardwareBuffer buffer = SurfaceControl.captureLayers(
- wc.getSurfaceControl(), bounds, 1);
-
- if (buffer == null || buffer.getHardwareBuffer() == null) {
- return false;
- }
-
- GraphicBuffer graphicBuffer = GraphicBuffer.createFromHardwareBuffer(
- buffer.getHardwareBuffer());
- SurfaceControl screenshot = mService.mWindowManager.mSurfaceControlFactory.apply(null)
- .setName(wc.getName() + " - Organizer Screenshot")
- .setFormat(PixelFormat.TRANSLUCENT)
- .setParent(wc.getParentSurfaceControl())
- .setSecure(buffer.containsSecureLayers())
- .setCallsite("WindowOrganizerController.takeScreenshot")
- .setBLASTLayer()
- .build();
-
- SurfaceControl.Transaction transaction = mService.mWindowManager.mTransactionFactory.get();
- transaction.setBuffer(screenshot, graphicBuffer);
- transaction.setColorSpace(screenshot, buffer.getColorSpace());
- transaction.apply();
-
- outSurfaceControl.copyFrom(screenshot, "WindowOrganizerController.takeScreenshot");
- return true;
- }
-
- @Override
public void registerTransitionPlayer(ITransitionPlayer player) {
enforceTaskPermission("registerTransitionPlayer()");
final long ident = Binder.clearCallingIdentity();
diff --git a/services/core/java/com/android/server/wm/WindowOrientationListener.java b/services/core/java/com/android/server/wm/WindowOrientationListener.java
index 3e099fb..249880e 100644
--- a/services/core/java/com/android/server/wm/WindowOrientationListener.java
+++ b/services/core/java/com/android/server/wm/WindowOrientationListener.java
@@ -31,9 +31,7 @@
import android.os.Handler;
import android.os.SystemClock;
import android.os.SystemProperties;
-import android.os.UserHandle;
import android.provider.DeviceConfig;
-import android.provider.Settings;
import android.rotationresolver.RotationResolverInternal;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
@@ -66,7 +64,6 @@
private static final boolean USE_GRAVITY_SENSOR = false;
private static final int DEFAULT_BATCH_LATENCY = 100000;
- private static final int DEFAULT_ROTATION_RESOLVER_ENABLED = 0; // disabled
private static final String KEY_ROTATION_RESOLVER_TIMEOUT = "rotation_resolver_timeout_millis";
private static final long DEFAULT_ROTATION_RESOLVER_TIMEOUT_MILLIS = 700L;
@@ -278,11 +275,7 @@
* screen rotation.
*/
@VisibleForTesting
- boolean isRotationResolverEnabled() {
- return Settings.Secure.getIntForUser(mContext.getContentResolver(),
- Settings.Secure.CAMERA_AUTOROTATE, DEFAULT_ROTATION_RESOLVER_ENABLED,
- UserHandle.USER_CURRENT) == 1;
- }
+ abstract boolean isRotationResolverEnabled();
/**
* Called when the rotation view of the device has changed.
@@ -1076,6 +1069,9 @@
private boolean mRotationEvaluationScheduled;
private long mRotationResolverTimeoutMillis;
private final ActivityTaskManagerInternal mActivityTaskManagerInternal;
+ private int mCurrentCallbackId = 0;
+ private Runnable mCancelRotationResolverRequest;
+
OrientationSensorJudge() {
super();
setupRotationResolverParameters();
@@ -1142,8 +1138,6 @@
RotationResolverInternal.class);
}
- final CancellationSignal cancellationSignal = new CancellationSignal();
-
String packageName = null;
if (mActivityTaskManagerInternal != null) {
final WindowProcessController controller =
@@ -1155,16 +1149,40 @@
}
}
+ mCurrentCallbackId++;
+
+ if (mCancelRotationResolverRequest != null) {
+ getHandler().removeCallbacks(mCancelRotationResolverRequest);
+ }
+ final CancellationSignal cancellationSignal = new CancellationSignal();
+ mCancelRotationResolverRequest = cancellationSignal::cancel;
+ getHandler().postDelayed(
+ mCancelRotationResolverRequest, mRotationResolverTimeoutMillis);
+
mRotationResolverService.resolveRotation(
new RotationResolverInternal.RotationResolverCallbackInternal() {
+ private final int mCallbackId = mCurrentCallbackId;
@Override
public void onSuccess(int result) {
- finalizeRotation(result);
+ finalizeRotationIfFresh(result);
}
@Override
public void onFailure(int error) {
- finalizeRotation(reportedRotation);
+ finalizeRotationIfFresh(reportedRotation);
+ }
+
+ private void finalizeRotationIfFresh(int rotation) {
+ // Ignore the callback if it's not the latest.
+ if (mCallbackId == mCurrentCallbackId) {
+ getHandler().removeCallbacks(mCancelRotationResolverRequest);
+ finalizeRotation(rotation);
+ } else {
+ Slog.d(TAG, String.format(
+ "An outdated callback received [%s vs. %s]. Ignoring "
+ + "it.",
+ mCallbackId, mCurrentCallbackId));
+ }
}
},
packageName,
@@ -1172,8 +1190,6 @@
mCurrentRotation,
mRotationResolverTimeoutMillis,
cancellationSignal);
- getHandler().postDelayed(cancellationSignal::cancel,
- mRotationResolverTimeoutMillis);
} else {
finalizeRotation(reportedRotation);
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 4eff18c..d09cc46 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2309,7 +2309,7 @@
// When the window configuration changed, we need to update the IME control target in
// case the app may lose the IME inets control when exiting from split-screen mode, or the
// IME parent may failed to attach to the app during rotating the screen.
- // See DisplayContent#isImeAttachedToApp, DisplayContent#isImeControlledByApp
+ // See DisplayContent#shouldImeAttachedToApp, DisplayContent#isImeControlledByApp
if (windowConfigChanged) {
getDisplayContent().updateImeControlTarget();
}
@@ -2409,18 +2409,22 @@
final boolean startingWindow = mAttrs.type == TYPE_APPLICATION_STARTING;
if (startingWindow) {
ProtoLog.d(WM_DEBUG_STARTING_WINDOW, "Starting window removed %s", this);
- }
-
- if (startingWindow && StartingSurfaceController.DEBUG_ENABLE_SHELL_DRAWER) {
// Cancel the remove starting window animation on shell. The main window might changed
// during animating, checking for all windows would be safer.
if (mActivityRecord != null) {
- mActivityRecord.forAllWindows(w -> {
+ mActivityRecord.forAllWindowsUnchecked(w -> {
if (w.isSelfAnimating(0, ANIMATION_TYPE_STARTING_REVEAL)) {
w.cancelAnimation();
+ return true;
}
+ return false;
}, true);
}
+ } else if (mAttrs.type == TYPE_BASE_APPLICATION
+ && isSelfAnimating(0, ANIMATION_TYPE_STARTING_REVEAL)) {
+ // Cancel the remove starting window animation in case the binder dead before remove
+ // splash window.
+ cancelAnimation();
}
ProtoLog.v(WM_DEBUG_FOCUS, "Remove client=%x, surfaceController=%s Callers=%s",
@@ -2428,7 +2432,6 @@
mWinAnimator.mSurfaceController,
Debug.getCallers(5));
-
final long origId = Binder.clearCallingIdentity();
try {
@@ -4852,8 +4855,9 @@
// (i.e. Like {@link DisplayContent.ImeContainer#skipImeWindowsDuringTraversal}, the IME
// window will be ignored to traverse when the IME target is still in split-screen mode).
if (isImeLayeringTarget()
- && !getDisplayContent().getDefaultTaskDisplayArea().isSplitScreenModeActivated()) {
- if (getDisplayContent().forAllImeWindows(callback, traverseTopToBottom)) {
+ && (!mDisplayContent.getDefaultTaskDisplayArea().isSplitScreenModeActivated()
+ || getTask() == null)) {
+ if (mDisplayContent.forAllImeWindows(callback, traverseTopToBottom)) {
return true;
}
}
diff --git a/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp b/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
index db52683..f439777 100644
--- a/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
+++ b/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
@@ -293,8 +293,8 @@
auto mode = read<int8_t>(metadata).value_or(STDIN);
if (mode == LOCAL_FILE) {
// local file and possibly signature
- return openLocalFile(env, jni, shellCommand, size,
- std::string(metadata.data, metadata.size));
+ auto dataSize = le32toh(read<int32_t>(metadata).value_or(0));
+ return openLocalFile(env, jni, shellCommand, size, std::string(metadata.data, dataSize));
}
if (!shellCommand) {
diff --git a/services/core/jni/gnss/GnssMeasurementCallback.cpp b/services/core/jni/gnss/GnssMeasurementCallback.cpp
index 646aabd..dd9a525 100644
--- a/services/core/jni/gnss/GnssMeasurementCallback.cpp
+++ b/services/core/jni/gnss/GnssMeasurementCallback.cpp
@@ -54,6 +54,7 @@
jmethodID method_reportMeasurementData;
jmethodID method_satellitePvtBuilderBuild;
jmethodID method_satellitePvtBuilderCtor;
+jmethodID method_satellitePvtBuilderSetFlags;
jmethodID method_satellitePvtBuilderSetPositionEcef;
jmethodID method_satellitePvtBuilderSetVelocityEcef;
jmethodID method_satellitePvtBuilderSetClockInfo;
@@ -89,6 +90,9 @@
jclass satellitePvtBuilder = env->FindClass("android/location/SatellitePvt$Builder");
class_satellitePvtBuilder = (jclass)env->NewGlobalRef(satellitePvtBuilder);
method_satellitePvtBuilderCtor = env->GetMethodID(class_satellitePvtBuilder, "<init>", "()V");
+ method_satellitePvtBuilderSetFlags =
+ env->GetMethodID(class_satellitePvtBuilder, "setFlags",
+ "(I)Landroid/location/SatellitePvt$Builder;");
method_satellitePvtBuilderSetPositionEcef =
env->GetMethodID(class_satellitePvtBuilder, "setPositionEcef",
"(Landroid/location/SatellitePvt$PositionEcef;)"
@@ -313,22 +317,33 @@
if (measurement.flags & static_cast<uint32_t>(GnssMeasurement::HAS_SATELLITE_PVT)) {
const SatellitePvt& satellitePvt = measurement.satellitePvt;
- jobject positionEcef = env->NewObject(class_positionEcef, method_positionEcef,
- satellitePvt.satPosEcef.posXMeters,
- satellitePvt.satPosEcef.posYMeters,
- satellitePvt.satPosEcef.posZMeters,
- satellitePvt.satPosEcef.ureMeters);
- jobject velocityEcef =
- env->NewObject(class_velocityEcef, method_velocityEcef,
- satellitePvt.satVelEcef.velXMps, satellitePvt.satVelEcef.velYMps,
- satellitePvt.satVelEcef.velZMps, satellitePvt.satVelEcef.ureRateMps);
- jobject clockInfo = env->NewObject(class_clockInfo, method_clockInfo,
- satellitePvt.satClockInfo.satHardwareCodeBiasMeters,
- satellitePvt.satClockInfo.satTimeCorrectionMeters,
- satellitePvt.satClockInfo.satClkDriftMps);
+ uint16_t satFlags = static_cast<uint16_t>(satellitePvt.flags);
+ jobject positionEcef = nullptr;
+ jobject velocityEcef = nullptr;
+ jobject clockInfo = nullptr;
+
+ if (satFlags & SatellitePvt::HAS_POSITION_VELOCITY_CLOCK_INFO) {
+ positionEcef = env->NewObject(class_positionEcef, method_positionEcef,
+ satellitePvt.satPosEcef.posXMeters,
+ satellitePvt.satPosEcef.posYMeters,
+ satellitePvt.satPosEcef.posZMeters,
+ satellitePvt.satPosEcef.ureMeters);
+ velocityEcef =
+ env->NewObject(class_velocityEcef, method_velocityEcef,
+ satellitePvt.satVelEcef.velXMps, satellitePvt.satVelEcef.velYMps,
+ satellitePvt.satVelEcef.velZMps,
+ satellitePvt.satVelEcef.ureRateMps);
+ clockInfo = env->NewObject(class_clockInfo, method_clockInfo,
+ satellitePvt.satClockInfo.satHardwareCodeBiasMeters,
+ satellitePvt.satClockInfo.satTimeCorrectionMeters,
+ satellitePvt.satClockInfo.satClkDriftMps);
+ }
+
jobject satellitePvtBuilderObject =
env->NewObject(class_satellitePvtBuilder, method_satellitePvtBuilderCtor);
+ env->CallObjectMethod(satellitePvtBuilderObject, method_satellitePvtBuilderSetFlags,
+ satellitePvt.flags);
env->CallObjectMethod(satellitePvtBuilderObject, method_satellitePvtBuilderSetPositionEcef,
positionEcef);
env->CallObjectMethod(satellitePvtBuilderObject, method_satellitePvtBuilderSetVelocityEcef,
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 23a67b7..8089fb1 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -1754,12 +1754,39 @@
if (userHandle == UserHandle.USER_SYSTEM) {
mStateCache.setDeviceProvisioned(policy.mUserSetupComplete);
}
+
+ migrateDeviceOwnerProtectedPackagesToOwners(userHandle, policy);
}
return policy;
}
}
/**
+ * Only used by {@link #getUserData(int)} to migrate <b>existing</b> device owner protected
+ * packages that were stored in {@link DevicePolicyData#mUserControlDisabledPackages} to
+ * {@link Owners} because the device owner protected packages are now stored on a per device
+ * owner basis instead of on a per user basis.
+ *
+ * Any calls to {@link #setUserControlDisabledPackages(ComponentName, List)} would now store
+ * the device owner protected packages in {@link Owners} instead of {@link DevicePolicyData}.
+ * @param userHandle The device owner user
+ * @param policy The policy data of the device owner user
+ */
+ private void migrateDeviceOwnerProtectedPackagesToOwners(
+ int userHandle, DevicePolicyData policy) {
+ ComponentName deviceOwnerComponent = getOwnerComponent(userHandle);
+ if (isDeviceOwner(deviceOwnerComponent, userHandle)
+ && !policy.mUserControlDisabledPackages.isEmpty()) {
+ mOwners.setDeviceOwnerProtectedPackages(
+ deviceOwnerComponent.getPackageName(),
+ policy.mUserControlDisabledPackages);
+
+ policy.mUserControlDisabledPackages = new ArrayList<>();
+ saveSettingsLocked(userHandle);
+ }
+ }
+
+ /**
* Creates and loads the policy data from xml for data that is shared between
* various profiles of a user. In contrast to {@link #getUserData(int)}
* it allows access to data of users other than the calling user.
@@ -2863,7 +2890,6 @@
updateMaximumTimeToLockLocked(userHandle);
updateLockTaskPackagesLocked(policy.mLockTaskPackages, userHandle);
updateLockTaskFeaturesLocked(policy.mLockTaskFeatures, userHandle);
- updateUserControlDisabledPackagesLocked(policy.mUserControlDisabledPackages);
if (policy.mStatusBarDisabled) {
setStatusBarDisabledInternal(policy.mStatusBarDisabled, userHandle);
}
@@ -2907,10 +2933,6 @@
}
}
- private void updateUserControlDisabledPackagesLocked(List<String> packages) {
- mInjector.getPackageManagerInternal().setDeviceOwnerProtectedPackages(packages);
- }
-
private void updateLockTaskFeaturesLocked(int flags, int userId) {
long ident = mInjector.binderClearCallingIdentity();
try {
@@ -7848,56 +7870,52 @@
void sendDeviceOwnerCommand(String action, Bundle extras) {
final int deviceOwnerUserId;
+ final ComponentName receiverComponent;
synchronized (getLockObject()) {
deviceOwnerUserId = mOwners.getDeviceOwnerUserId();
+ receiverComponent = mOwners.getDeviceOwnerComponent();
}
-
- ComponentName receiverComponent = null;
- if (action.equals(DeviceAdminReceiver.ACTION_NETWORK_LOGS_AVAILABLE)) {
- receiverComponent = resolveDelegateReceiver(DELEGATION_NETWORK_LOGGING, action,
- deviceOwnerUserId);
- }
- if (action.equals(DeviceAdminReceiver.ACTION_SECURITY_LOGS_AVAILABLE)) {
- receiverComponent = resolveDelegateReceiver(DELEGATION_SECURITY_LOGGING, action,
- deviceOwnerUserId);
- }
- if (receiverComponent == null) {
- synchronized (getLockObject()) {
- receiverComponent = mOwners.getDeviceOwnerComponent();
- }
- }
- sendActiveAdminCommand(action, extras, deviceOwnerUserId, receiverComponent);
+ sendActiveAdminCommand(action, extras, deviceOwnerUserId, receiverComponent,
+ /* inForeground */ false);
}
void sendDeviceOwnerOrProfileOwnerCommand(String action, Bundle extras, int userId) {
if (userId == UserHandle.USER_ALL) {
userId = UserHandle.USER_SYSTEM;
}
+ boolean inForeground = false;
ComponentName receiverComponent = null;
if (action.equals(DeviceAdminReceiver.ACTION_NETWORK_LOGS_AVAILABLE)) {
+ inForeground = true;
receiverComponent = resolveDelegateReceiver(DELEGATION_NETWORK_LOGGING, action, userId);
}
if (action.equals(DeviceAdminReceiver.ACTION_SECURITY_LOGS_AVAILABLE)) {
+ inForeground = true;
receiverComponent = resolveDelegateReceiver(
DELEGATION_SECURITY_LOGGING, action, userId);
}
if (receiverComponent == null) {
receiverComponent = getOwnerComponent(userId);
}
- sendActiveAdminCommand(action, extras, userId, receiverComponent);
+ sendActiveAdminCommand(action, extras, userId, receiverComponent, inForeground);
}
private void sendProfileOwnerCommand(String action, Bundle extras, @UserIdInt int userId) {
- sendActiveAdminCommand(action, extras, userId, mOwners.getProfileOwnerComponent(userId));
+ sendActiveAdminCommand(action, extras, userId, mOwners.getProfileOwnerComponent(userId),
+ /* inForeground */ false);
}
private void sendActiveAdminCommand(String action, Bundle extras,
- @UserIdInt int userId, ComponentName receiverComponent) {
+ @UserIdInt int userId, ComponentName receiverComponent, boolean inForeground) {
final Intent intent = new Intent(action);
intent.setComponent(receiverComponent);
if (extras != null) {
intent.putExtras(extras);
}
+ if (inForeground) {
+ intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+ }
+
if (VERBOSE_LOG) {
Slogf.v(LOG_TAG, "sendActiveAdminCommand(): broadcasting " + action + " to "
+ receiverComponent.flattenToShortString() + " on user " + userId);
@@ -8759,7 +8777,6 @@
updateLockTaskPackagesLocked(policy.mLockTaskPackages, userId);
policy.mLockTaskFeatures = DevicePolicyManager.LOCK_TASK_FEATURE_NONE;
policy.mUserControlDisabledPackages.clear();
- updateUserControlDisabledPackagesLocked(policy.mUserControlDisabledPackages);
saveSettingsLocked(userId);
try {
@@ -11987,8 +12004,8 @@
Preconditions.checkCallAuthorization(isDeviceOwner(caller));
UserHandle userHandle = caller.getUserHandle();
- if (mIsAutomotive) {
- Slogf.v(LOG_TAG, "setLocationEnabled(%s, %b): ignoring for user %s on automotive build",
+ if (mIsAutomotive && !locationEnabled) {
+ Slogf.i(LOG_TAG, "setLocationEnabled(%s, %b): ignoring for user %s on automotive build",
who.flattenToShortString(), locationEnabled, userHandle);
return;
}
@@ -11996,8 +12013,8 @@
mInjector.binderWithCleanCallingIdentity(() -> {
boolean wasLocationEnabled = mInjector.getLocationManager().isLocationEnabledForUser(
userHandle);
- Slogf.v(LOG_TAG, "calling locationManager.setLocationEnabledForUser(%b, %s)",
- locationEnabled, userHandle);
+ Slogf.v(LOG_TAG, "calling locationMgr.setLocationEnabledForUser(%b, %s) when it was %b",
+ locationEnabled, userHandle, wasLocationEnabled);
mInjector.getLocationManager().setLocationEnabledForUser(locationEnabled, userHandle);
// make a best effort to only show the notification if the admin is actually enabling
@@ -16199,14 +16216,14 @@
@Override
public void setUserControlDisabledPackages(ComponentName who, List<String> packages) {
Objects.requireNonNull(who, "ComponentName is null");
- Preconditions.checkNotNull(packages, "packages is null");
+ Objects.requireNonNull(packages, "packages is null");
final CallerIdentity caller = getCallerIdentity(who);
Preconditions.checkCallAuthorization(isDeviceOwner(caller));
checkCanExecuteOrThrowUnsafe(
DevicePolicyManager.OPERATION_SET_USER_CONTROL_DISABLED_PACKAGES);
synchronized (getLockObject()) {
- setUserControlDisabledPackagesLocked(caller.getUserId(), packages);
+ mOwners.setDeviceOwnerProtectedPackages(who.getPackageName(), packages);
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.SET_USER_CONTROL_DISABLED_PACKAGES)
.setAdmin(who)
@@ -16215,15 +16232,6 @@
}
}
- private void setUserControlDisabledPackagesLocked(int userHandle, List<String> packages) {
- final DevicePolicyData policy = getUserData(userHandle);
- policy.mUserControlDisabledPackages = packages;
-
- // Store the settings persistently.
- saveSettingsLocked(userHandle);
- updateUserControlDisabledPackagesLocked(packages);
- }
-
@Override
public List<String> getUserControlDisabledPackages(ComponentName who) {
Objects.requireNonNull(who, "ComponentName is null");
@@ -16232,9 +16240,7 @@
Preconditions.checkCallAuthorization(isDeviceOwner(caller));
synchronized (getLockObject()) {
- final List<String> packages =
- getUserData(caller.getUserId()).mUserControlDisabledPackages;
- return packages == null ? Collections.EMPTY_LIST : packages;
+ return mOwners.getDeviceOwnerProtectedPackages(who.getPackageName());
}
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
index 7fdd6ee..fd09e3f 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
@@ -62,6 +62,7 @@
import java.io.InputStream;
import java.time.LocalDate;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -97,10 +98,13 @@
// Holds "context" for device-owner, this must not be show up before device-owner.
private static final String TAG_DEVICE_OWNER_CONTEXT = "device-owner-context";
private static final String TAG_DEVICE_OWNER_TYPE = "device-owner-type";
+ private static final String TAG_DEVICE_OWNER_PROTECTED_PACKAGES =
+ "device-owner-protected-packages";
private static final String ATTR_NAME = "name";
private static final String ATTR_PACKAGE = "package";
private static final String ATTR_COMPONENT_NAME = "component";
+ private static final String ATTR_SIZE = "size";
private static final String ATTR_REMOTE_BUGREPORT_URI = "remoteBugreportUri";
private static final String ATTR_REMOTE_BUGREPORT_HASH = "remoteBugreportHash";
private static final String ATTR_USERID = "userId";
@@ -129,6 +133,8 @@
// Device owner type for a managed device.
private final ArrayMap<String, Integer> mDeviceOwnerTypes = new ArrayMap<>();
+ private final ArrayMap<String, List<String>> mDeviceOwnerProtectedPackages = new ArrayMap<>();
+
private int mDeviceOwnerUserId = UserHandle.USER_NULL;
// Internal state for the profile owner packages.
@@ -216,6 +222,12 @@
pushToActivityTaskManagerLocked();
pushToActivityManagerLocked();
pushToAppOpsLocked();
+
+ for (ArrayMap.Entry<String, List<String>> entry :
+ mDeviceOwnerProtectedPackages.entrySet()) {
+ mPackageManagerInternal.setDeviceOwnerProtectedPackages(
+ entry.getKey(), entry.getValue());
+ }
}
}
@@ -343,6 +355,12 @@
void clearDeviceOwner() {
synchronized (mLock) {
mDeviceOwnerTypes.remove(mDeviceOwner.packageName);
+ List<String> protectedPackages =
+ mDeviceOwnerProtectedPackages.remove(mDeviceOwner.packageName);
+ if (protectedPackages != null) {
+ mPackageManagerInternal.setDeviceOwnerProtectedPackages(
+ mDeviceOwner.packageName, new ArrayList<>());
+ }
mDeviceOwner = null;
mDeviceOwnerUserId = UserHandle.USER_NULL;
@@ -394,6 +412,12 @@
void transferDeviceOwnership(ComponentName target) {
synchronized (mLock) {
Integer previousDeviceOwnerType = mDeviceOwnerTypes.remove(mDeviceOwner.packageName);
+ List<String> previousProtectedPackages =
+ mDeviceOwnerProtectedPackages.remove(mDeviceOwner.packageName);
+ if (previousProtectedPackages != null) {
+ mPackageManagerInternal.setDeviceOwnerProtectedPackages(
+ mDeviceOwner.packageName, new ArrayList<>());
+ }
// We don't set a name because it's not used anyway.
// See DevicePolicyManagerService#getDeviceOwnerName
mDeviceOwner = new OwnerInfo(null, target,
@@ -403,6 +427,10 @@
if (previousDeviceOwnerType != null) {
mDeviceOwnerTypes.put(mDeviceOwner.packageName, previousDeviceOwnerType);
}
+ if (previousProtectedPackages != null) {
+ mDeviceOwnerProtectedPackages.put(
+ mDeviceOwner.packageName, previousProtectedPackages);
+ }
pushToPackageManagerLocked();
pushToActivityTaskManagerLocked();
pushToActivityManagerLocked();
@@ -583,7 +611,7 @@
}
}
- /** Sets the user restrictions migrated flag, and also writes to the file. */
+ /** Sets the user restrictions migrated flag, and also writes to the file. */
void setProfileOwnerUserRestrictionsMigrated(int userId) {
synchronized (mLock) {
OwnerInfo profileOwner = mProfileOwners.get(userId);
@@ -594,8 +622,10 @@
}
}
- /** Sets the indicator that the profile owner manages an organization-owned device,
- * then write to file. */
+ /**
+ * Sets the indicator that the profile owner manages an organization-owned device,
+ * then write to file.
+ */
void markProfileOwnerOfOrganizationOwnedDevice(int userId) {
synchronized (mLock) {
OwnerInfo profileOwner = mProfileOwners.get(userId);
@@ -640,6 +670,33 @@
}
}
+ void setDeviceOwnerProtectedPackages(String packageName, List<String> protectedPackages) {
+ synchronized (mLock) {
+ if (!hasDeviceOwner()) {
+ Slog.e(TAG,
+ "Attempting to set device owner protected packages when there is no "
+ + "device owner");
+ return;
+ } else if (!mDeviceOwner.packageName.equals(packageName)) {
+ Slog.e(TAG, "Attempting to set device owner protected packages when the provided "
+ + "package name " + packageName
+ + " does not match the device owner package name");
+ return;
+ }
+
+ mDeviceOwnerProtectedPackages.put(packageName, protectedPackages);
+ mPackageManagerInternal.setDeviceOwnerProtectedPackages(packageName, protectedPackages);
+ writeDeviceOwner();
+ }
+ }
+
+ List<String> getDeviceOwnerProtectedPackages(String packageName) {
+ synchronized (mLock) {
+ return mDeviceOwnerProtectedPackages.containsKey(packageName)
+ ? mDeviceOwnerProtectedPackages.get(packageName) : Collections.emptyList();
+ }
+ }
+
private boolean readLegacyOwnerFileLocked(File file) {
if (!file.exists()) {
// Already migrated or the device has no owners.
@@ -649,8 +706,8 @@
InputStream input = new AtomicFile(file).openRead();
TypedXmlPullParser parser = Xml.resolvePullParser(input);
int type;
- while ((type=parser.next()) != TypedXmlPullParser.END_DOCUMENT) {
- if (type!=TypedXmlPullParser.START_TAG) {
+ while ((type = parser.next()) != TypedXmlPullParser.END_DOCUMENT) {
+ if (type != TypedXmlPullParser.START_TAG) {
continue;
}
@@ -700,7 +757,7 @@
}
}
input.close();
- } catch (XmlPullParserException|IOException e) {
+ } catch (XmlPullParserException | IOException e) {
Slog.e(TAG, "Error parsing device-owner file", e);
}
return true;
@@ -936,6 +993,21 @@
}
}
+ if (!mDeviceOwnerProtectedPackages.isEmpty()) {
+ for (ArrayMap.Entry<String, List<String>> entry :
+ mDeviceOwnerProtectedPackages.entrySet()) {
+ List<String> protectedPackages = entry.getValue();
+
+ out.startTag(null, TAG_DEVICE_OWNER_PROTECTED_PACKAGES);
+ out.attribute(null, ATTR_PACKAGE, entry.getKey());
+ out.attributeInt(null, ATTR_SIZE, protectedPackages.size());
+ for (int i = 0, size = protectedPackages.size(); i < size; i++) {
+ out.attribute(null, ATTR_NAME + i, protectedPackages.get(i));
+ }
+ out.endTag(null, TAG_DEVICE_OWNER_PROTECTED_PACKAGES);
+ }
+ }
+
if (mSystemUpdatePolicy != null) {
out.startTag(null, TAG_SYSTEM_UPDATE_POLICY);
mSystemUpdatePolicy.saveToXml(out);
@@ -1002,6 +1074,15 @@
DEVICE_OWNER_TYPE_DEFAULT);
mDeviceOwnerTypes.put(packageName, deviceOwnerType);
break;
+ case TAG_DEVICE_OWNER_PROTECTED_PACKAGES:
+ packageName = parser.getAttributeValue(null, ATTR_PACKAGE);
+ int protectedPackagesSize = parser.getAttributeInt(null, ATTR_SIZE, 0);
+ List<String> protectedPackages = new ArrayList<>();
+ for (int i = 0; i < protectedPackagesSize; i++) {
+ protectedPackages.add(parser.getAttributeValue(null, ATTR_NAME + i));
+ }
+ mDeviceOwnerProtectedPackages.put(packageName, protectedPackages);
+ break;
default:
Slog.e(TAG, "Unexpected tag: " + tag);
return false;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/SecurityLogMonitor.java b/services/devicepolicy/java/com/android/server/devicepolicy/SecurityLogMonitor.java
index 3c445ca..c29de90 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/SecurityLogMonitor.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/SecurityLogMonitor.java
@@ -226,7 +226,7 @@
Slog.i(TAG, "Resumed.");
try {
- notifyDeviceOwnerIfNeeded(false /* force */);
+ notifyDeviceOwnerOrProfileOwnerIfNeeded(false /* force */);
} catch (InterruptedException e) {
Log.w(TAG, "Thread interrupted.", e);
}
@@ -439,7 +439,7 @@
saveLastEvents(newLogs);
newLogs.clear();
- notifyDeviceOwnerIfNeeded(force);
+ notifyDeviceOwnerOrProfileOwnerIfNeeded(force);
} catch (IOException e) {
Log.e(TAG, "Failed to read security log", e);
} catch (InterruptedException e) {
@@ -460,8 +460,9 @@
Slog.i(TAG, "MonitorThread exit.");
}
- private void notifyDeviceOwnerIfNeeded(boolean force) throws InterruptedException {
- boolean allowRetrievalAndNotifyDO = false;
+ private void notifyDeviceOwnerOrProfileOwnerIfNeeded(boolean force)
+ throws InterruptedException {
+ boolean allowRetrievalAndNotifyDOOrPO = false;
mLock.lockInterruptibly();
try {
if (mPaused) {
@@ -471,16 +472,16 @@
if (logSize >= BUFFER_ENTRIES_NOTIFICATION_LEVEL || (force && logSize > 0)) {
// Allow DO to retrieve logs if too many pending logs or if forced.
if (!mAllowedToRetrieve) {
- allowRetrievalAndNotifyDO = true;
+ allowRetrievalAndNotifyDOOrPO = true;
}
if (DEBUG) Slog.d(TAG, "Number of log entries over threshold: " + logSize);
}
if (logSize > 0 && SystemClock.elapsedRealtime() >= mNextAllowedRetrievalTimeMillis) {
// Rate limit reset
- allowRetrievalAndNotifyDO = true;
+ allowRetrievalAndNotifyDOOrPO = true;
if (DEBUG) Slog.d(TAG, "Timeout reached");
}
- if (allowRetrievalAndNotifyDO) {
+ if (allowRetrievalAndNotifyDOOrPO) {
mAllowedToRetrieve = true;
// Set the timeout to retry the notification if the DO misses it.
mNextAllowedRetrievalTimeMillis = SystemClock.elapsedRealtime()
@@ -489,10 +490,10 @@
} finally {
mLock.unlock();
}
- if (allowRetrievalAndNotifyDO) {
- Slog.i(TAG, "notify DO");
- mService.sendDeviceOwnerCommand(DeviceAdminReceiver.ACTION_SECURITY_LOGS_AVAILABLE,
- null);
+ if (allowRetrievalAndNotifyDOOrPO) {
+ Slog.i(TAG, "notify DO or PO");
+ mService.sendDeviceOwnerOrProfileOwnerCommand(
+ DeviceAdminReceiver.ACTION_SECURITY_LOGS_AVAILABLE, null, mEnabledUser);
}
}
diff --git a/services/incremental/IncrementalService.cpp b/services/incremental/IncrementalService.cpp
index 24699d9..8b816d0 100644
--- a/services/incremental/IncrementalService.cpp
+++ b/services/incremental/IncrementalService.cpp
@@ -1174,7 +1174,8 @@
return -EINVAL;
}
if (auto err = mIncFs->makeFile(ifs->control, normPath, mode, id, params); err) {
- LOG(ERROR) << "Internal error: storageId " << storage << " failed to makeFile: " << err;
+ LOG(ERROR) << "Internal error: storageId " << storage << " failed to makeFile [" << normPath
+ << "]: " << err;
return err;
}
if (params.size > 0) {
diff --git a/services/incremental/path.cpp b/services/incremental/path.cpp
index bf4e9616..73e00ae 100644
--- a/services/incremental/path.cpp
+++ b/services/incremental/path.cpp
@@ -171,7 +171,9 @@
}
details::CStrWrapper::CStrWrapper(std::string_view sv) {
- if (sv[sv.size()] == '\0') {
+ if (!sv.data()) {
+ mCstr = "";
+ } else if (sv[sv.size()] == '\0') {
mCstr = sv.data();
} else {
mCopy.emplace(sv);
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 1e4b248..7e718e5 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -1793,7 +1793,7 @@
t.traceEnd();
t.traceBegin("StartFontManagerService");
- mSystemServiceManager.startService(FontManagerService.Lifecycle.class);
+ mSystemServiceManager.startService(new FontManagerService.Lifecycle(context, safeMode));
t.traceEnd();
t.traceBegin("StartTextServicesManager");
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 5222511..d5e1cd6 100644
--- a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
@@ -175,6 +175,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
+import java.util.Random;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.LongConsumer;
@@ -2269,17 +2270,46 @@
() -> CompatChanges.isChangeEnabled(
eq(AlarmManager.ENFORCE_MINIMUM_WINDOW_ON_INEXACT_ALARMS),
anyString(), any(UserHandle.class)));
- final long minWindow = 73;
+ final int minWindow = 73;
setDeviceConfigLong(KEY_MIN_WINDOW, minWindow);
+ final Random random = new Random(42);
+
// 0 is WINDOW_EXACT and < 0 is WINDOW_HEURISTIC.
for (int window = 1; window <= minWindow; window++) {
final PendingIntent pi = getNewMockPendingIntent();
+ final long futurity = random.nextInt(minWindow);
+
+ setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + futurity, window, pi, 0, 0,
+ TEST_CALLING_UID, null);
+
+ final long minAllowed = (long) (futurity * 0.75); // This will always be <= minWindow.
+
+ assertEquals(1, mService.mAlarmStore.size());
+ final Alarm a = mService.mAlarmStore.remove(unused -> true).get(0);
+ assertEquals(Math.max(minAllowed, window), a.windowLength);
+ }
+
+ for (int window = 1; window <= minWindow; window++) {
+ final PendingIntent pi = getNewMockPendingIntent();
+ final long futurity = 2 * minWindow + window; // implies (0.75 * futurity) > minWindow
+
+ setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + futurity, window, pi, 0, 0,
+ TEST_CALLING_UID, null);
+
+ assertEquals(1, mService.mAlarmStore.size());
+ final Alarm a = mService.mAlarmStore.remove(unused -> true).get(0);
+ assertEquals(minWindow, a.windowLength);
+ }
+
+ for (int i = 0; i < 20; i++) {
+ final long window = minWindow + random.nextInt(100);
+ final PendingIntent pi = getNewMockPendingIntent();
setTestAlarm(ELAPSED_REALTIME, 0, window, pi, 0, 0, TEST_CALLING_UID, null);
assertEquals(1, mService.mAlarmStore.size());
final Alarm a = mService.mAlarmStore.remove(unused -> true).get(0);
- assertEquals(minWindow, a.windowLength);
+ assertEquals(window, a.windowLength);
}
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java b/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java
index 9649570..e7a4c92 100644
--- a/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java
@@ -299,11 +299,13 @@
public void testGameMode() {
GameManagerService gameManagerService = new GameManagerService(mMockContext);
gameManagerService.onUserStarting(USER_ID_1);
-
+ gameManagerService.updateConfigsForUser(USER_ID_1, mPackageName);
mockModifyGameModeGranted();
-
assertEquals(GameManager.GAME_MODE_UNSUPPORTED,
gameManagerService.getGameMode(mPackageName, USER_ID_1));
+ // We need to make sure the mode is supported before setting it.
+ mockDeviceConfigAll();
+ gameManagerService.updateConfigsForUser(USER_ID_1, mPackageName);
gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_STANDARD, USER_ID_1);
assertEquals(GameManager.GAME_MODE_STANDARD,
gameManagerService.getGameMode(mPackageName, USER_ID_1));
@@ -370,11 +372,13 @@
*/
@Test
public void testGameModeMultipleUsers() {
+ mockModifyGameModeGranted();
+ mockDeviceConfigAll();
GameManagerService gameManagerService = new GameManagerService(mMockContext);
gameManagerService.onUserStarting(USER_ID_1);
gameManagerService.onUserStarting(USER_ID_2);
-
- mockModifyGameModeGranted();
+ gameManagerService.updateConfigsForUser(USER_ID_1, mPackageName);
+ gameManagerService.updateConfigsForUser(USER_ID_2, mPackageName);
// Set User 1 to Standard
gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_STANDARD, USER_ID_1);
@@ -603,4 +607,52 @@
gameManagerService.getConfig(mPackageName);
assertNull(config.getGameModeConfiguration(GameManager.GAME_MODE_PERFORMANCE));
}
+
+ /**
+ * Ensure that, if a game no longer supports any game modes, we set the game mode to
+ * UNSUPPORTED
+ */
+ @Test
+ public void testUnsetInvalidGameMode() throws Exception {
+ mockDeviceConfigNone();
+ mockModifyGameModeGranted();
+ GameManagerService gameManagerService = new GameManagerService(mMockContext);
+ gameManagerService.onUserStarting(USER_ID_1);
+ gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_PERFORMANCE, USER_ID_1);
+ gameManagerService.updateConfigsForUser(USER_ID_1, mPackageName);
+ assertEquals(GameManager.GAME_MODE_UNSUPPORTED,
+ gameManagerService.getGameMode(mPackageName, USER_ID_1));
+ }
+
+ /**
+ * Ensure that, if a game no longer supports a specific game mode, but supports STANDARD, we set
+ * the game mode to STANDARD.
+ */
+ @Test
+ public void testResetInvalidGameMode() throws Exception {
+ mockDeviceConfigPerformance();
+ mockModifyGameModeGranted();
+ GameManagerService gameManagerService = new GameManagerService(mMockContext);
+ gameManagerService.onUserStarting(USER_ID_1);
+ gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_BATTERY, USER_ID_1);
+ gameManagerService.updateConfigsForUser(USER_ID_1, mPackageName);
+ assertEquals(GameManager.GAME_MODE_STANDARD,
+ gameManagerService.getGameMode(mPackageName, USER_ID_1));
+ }
+
+ /**
+ * Ensure that if a game supports STANDARD, but is currently set to UNSUPPORTED, we set the game
+ * mode to STANDARD
+ */
+ @Test
+ public void testSetValidGameMode() throws Exception {
+ mockDeviceConfigPerformance();
+ mockModifyGameModeGranted();
+ GameManagerService gameManagerService = new GameManagerService(mMockContext);
+ gameManagerService.onUserStarting(USER_ID_1);
+ gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_UNSUPPORTED, USER_ID_1);
+ gameManagerService.updateConfigsForUser(USER_ID_1, mPackageName);
+ assertEquals(GameManager.GAME_MODE_STANDARD,
+ gameManagerService.getGameMode(mPackageName, USER_ID_1));
+ }
}
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 b367203..0dcc069 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
@@ -24,6 +24,7 @@
import static org.testng.Assert.expectThrows;
+import android.app.appsearch.AppSearchResult;
import android.app.appsearch.AppSearchSchema;
import android.app.appsearch.GenericDocument;
import android.app.appsearch.SearchResult;
@@ -39,16 +40,19 @@
import androidx.test.core.app.ApplicationProvider;
import com.android.server.appsearch.external.localstorage.converter.GenericDocumentToProtoConverter;
+import com.android.server.appsearch.external.localstorage.stats.InitializeStats;
import com.android.server.appsearch.external.localstorage.util.PrefixUtil;
import com.android.server.appsearch.proto.DocumentProto;
import com.android.server.appsearch.proto.GetOptimizeInfoResultProto;
import com.android.server.appsearch.proto.PersistType;
import com.android.server.appsearch.proto.PropertyConfigProto;
import com.android.server.appsearch.proto.PropertyProto;
+import com.android.server.appsearch.proto.PutResultProto;
import com.android.server.appsearch.proto.SchemaProto;
import com.android.server.appsearch.proto.SchemaTypeConfigProto;
import com.android.server.appsearch.proto.SearchResultProto;
import com.android.server.appsearch.proto.SearchSpecProto;
+import com.android.server.appsearch.proto.StatusProto;
import com.android.server.appsearch.proto.StringIndexingConfig;
import com.android.server.appsearch.proto.TermMatchType;
@@ -86,8 +90,6 @@
/*logger=*/ null);
}
- // TODO(b/175430168) add test to verify reset is working properly.
-
/**
* Ensure that we can rewrite an incoming schema type by adding the database as a prefix. While
* also keeping any other existing schema types that may already be part of Icing's persisted
@@ -486,6 +488,142 @@
}
@Test
+ public void testReset() throws Exception {
+ // Setup the index
+ Context context = ApplicationProvider.getApplicationContext();
+ File appsearchDir = mTemporaryFolder.newFolder();
+ AppSearchImpl appSearchImpl =
+ AppSearchImpl.create(
+ appsearchDir,
+ context,
+ VisibilityStore.NO_OP_USER_ID,
+ /*globalQuerierPackage=*/ "",
+ /*logger=*/ null);
+
+ // Insert schema
+ List<AppSearchSchema> schemas =
+ ImmutableList.of(
+ new AppSearchSchema.Builder("Type1").build(),
+ new AppSearchSchema.Builder("Type2").build());
+ appSearchImpl.setSchema(
+ context.getPackageName(),
+ "database1",
+ schemas,
+ /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
+ /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*forceOverride=*/ false,
+ /*version=*/ 0);
+
+ // Insert a valid doc
+ GenericDocument validDoc =
+ new GenericDocument.Builder<>("namespace1", "id1", "Type1").build();
+ appSearchImpl.putDocument(
+ context.getPackageName(), "database1", validDoc, /*logger=*/ null);
+
+ // Query it via global query. We use the same code again later so this is to make sure we
+ // have our global query configured right.
+ SearchResultPage results =
+ appSearchImpl.globalQuery(
+ /*queryExpression=*/ "",
+ new SearchSpec.Builder().addFilterSchemas("Type1").build(),
+ context.getPackageName(),
+ VisibilityStore.NO_OP_USER_ID,
+ /*logger=*/ null);
+ assertThat(results.getResults()).hasSize(1);
+ assertThat(results.getResults().get(0).getGenericDocument()).isEqualTo(validDoc);
+
+ // Create a doc with a malformed namespace
+ DocumentProto invalidDoc =
+ DocumentProto.newBuilder()
+ .setNamespace("invalidNamespace")
+ .setUri("id2")
+ .setSchema(context.getPackageName() + "$database1/Type1")
+ .build();
+ AppSearchException e =
+ expectThrows(
+ AppSearchException.class,
+ () -> PrefixUtil.getPrefix(invalidDoc.getNamespace()));
+ assertThat(e)
+ .hasMessageThat()
+ .isEqualTo(
+ "The prefixed value \"invalidNamespace\" doesn't contain a valid database"
+ + " name");
+
+ // Insert the invalid doc with an invalid namespace right into icing
+ PutResultProto putResultProto = appSearchImpl.mIcingSearchEngineLocked.put(invalidDoc);
+ assertThat(putResultProto.getStatus().getCode()).isEqualTo(StatusProto.Code.OK);
+
+ // Create a logger for capturing initialization to make sure we are logging the recovery
+ // process correctly.
+ AppSearchLoggerTest.TestLogger testLogger = new AppSearchLoggerTest.TestLogger();
+
+ // Initialize AppSearchImpl. This should cause a reset.
+ appSearchImpl.close();
+ appSearchImpl =
+ AppSearchImpl.create(
+ appsearchDir,
+ context,
+ VisibilityStore.NO_OP_USER_ID,
+ /*globalQuerierPackage=*/ context.getPackageName(),
+ testLogger);
+
+ // Check recovery state
+ InitializeStats initStats = testLogger.mInitializeStats;
+ assertThat(initStats).isNotNull();
+ assertThat(initStats.getStatusCode()).isEqualTo(AppSearchResult.RESULT_INTERNAL_ERROR);
+ assertThat(initStats.hasDeSync()).isFalse();
+ assertThat(initStats.getDocumentStoreRecoveryCause())
+ .isEqualTo(InitializeStats.RECOVERY_CAUSE_NONE);
+ // TODO(b/187879464): There should not be a recovery here, but icing lib reports one if the
+ // doc had no tokens. Once the mentioned bug is fixed, uncomment this.
+ // assertThat(initStats.getIndexRestorationCause())
+ // .isEqualTo(InitializeStats.RECOVERY_CAUSE_NONE);
+ assertThat(initStats.getSchemaStoreRecoveryCause())
+ .isEqualTo(InitializeStats.RECOVERY_CAUSE_NONE);
+ assertThat(initStats.getDocumentStoreDataStatus())
+ .isEqualTo(InitializeStats.DOCUMENT_STORE_DATA_STATUS_NO_DATA_LOSS);
+ assertThat(initStats.hasReset()).isTrue();
+ assertThat(initStats.getResetStatusCode()).isEqualTo(AppSearchResult.RESULT_OK);
+
+ // Make sure all our data is gone
+ assertThat(appSearchImpl.getSchema(context.getPackageName(), "database1").getSchemas())
+ .isEmpty();
+ results =
+ appSearchImpl.globalQuery(
+ /*queryExpression=*/ "",
+ new SearchSpec.Builder().addFilterSchemas("Type1").build(),
+ context.getPackageName(),
+ VisibilityStore.NO_OP_USER_ID,
+ /*logger=*/ null);
+ assertThat(results.getResults()).isEmpty();
+
+ // Make sure the index can now be used successfully
+ appSearchImpl.setSchema(
+ context.getPackageName(),
+ "database1",
+ Collections.singletonList(new AppSearchSchema.Builder("Type1").build()),
+ /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
+ /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*forceOverride=*/ false,
+ /*version=*/ 0);
+
+ // Insert a valid doc
+ appSearchImpl.putDocument(
+ context.getPackageName(), "database1", validDoc, /*logger=*/ null);
+
+ // Query it via global query.
+ results =
+ appSearchImpl.globalQuery(
+ /*queryExpression=*/ "",
+ new SearchSpec.Builder().addFilterSchemas("Type1").build(),
+ context.getPackageName(),
+ VisibilityStore.NO_OP_USER_ID,
+ /*logger=*/ null);
+ assertThat(results.getResults()).hasSize(1);
+ assertThat(results.getResults().get(0).getGenericDocument()).isEqualTo(validDoc);
+ }
+
+ @Test
public void testRewriteSearchSpec_oneInstance() throws Exception {
SearchSpecProto.Builder searchSpecProto = SearchSpecProto.newBuilder().setQuery("");
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 2aad275..b6bb394 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
@@ -68,7 +68,7 @@
}
// Test only not thread safe.
- public class TestLogger implements AppSearchLogger {
+ public static class TestLogger implements AppSearchLogger {
@Nullable CallStats mCallStats;
@Nullable PutDocumentStats mPutDocumentStats;
@Nullable InitializeStats mInitializeStats;
@@ -193,8 +193,7 @@
public void testAppSearchLoggerHelper_testCopyNativeStats_search() {
int nativeLatencyMillis = 4;
int nativeNumTerms = 5;
- // TODO(b/185804196) query length needs to be added in the native stats.
- // int nativeQueryLength = 6;
+ int nativeQueryLength = 6;
int nativeNumNamespacesFiltered = 7;
int nativeNumSchemaTypesFiltered = 8;
int nativeRequestedPageSize = 9;
@@ -211,6 +210,7 @@
QueryStatsProto.newBuilder()
.setLatencyMs(nativeLatencyMillis)
.setNumTerms(nativeNumTerms)
+ .setQueryLength(nativeQueryLength)
.setNumNamespacesFiltered(nativeNumNamespacesFiltered)
.setNumSchemaTypesFiltered(nativeNumSchemaTypesFiltered)
.setRequestedPageSize(nativeRequestedPageSize)
@@ -235,7 +235,7 @@
SearchStats sStats = qBuilder.build();
assertThat(sStats.getNativeLatencyMillis()).isEqualTo(nativeLatencyMillis);
assertThat(sStats.getTermCount()).isEqualTo(nativeNumTerms);
- // assertThat(sStats.getNativeQueryLength()).isEqualTo(nativeQueryLength);
+ assertThat(sStats.getQueryLength()).isEqualTo(nativeQueryLength);
assertThat(sStats.getFilteredNamespaceCount()).isEqualTo(nativeNumNamespacesFiltered);
assertThat(sStats.getFilteredSchemaTypeCount()).isEqualTo(nativeNumSchemaTypesFiltered);
assertThat(sStats.getRequestedPageSize()).isEqualTo(nativeRequestedPageSize);
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverterTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverterTest.java
index 0fe3903..77e0135 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverterTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverterTest.java
@@ -110,7 +110,7 @@
.TOKENIZER_TYPE_PLAIN)
.build())
.addProperty(
- new AppSearchSchema.Int64PropertyConfig.Builder("pubDate")
+ new AppSearchSchema.LongPropertyConfig.Builder("pubDate")
.setCardinality(
AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
.build())
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 2d03981..a71e532 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
@@ -168,7 +168,9 @@
.setSchemaStoreRecoveryLatencyMillis(nativeSchemaStoreRecoveryLatencyMillis)
.setDocumentStoreDataStatus(nativeDocumentStoreDataStatus)
.setDocumentCount(nativeNumDocuments)
- .setSchemaTypeCount(nativeNumSchemaTypes);
+ .setSchemaTypeCount(nativeNumSchemaTypes)
+ .setHasReset(true)
+ .setResetStatusCode(AppSearchResult.RESULT_INVALID_SCHEMA);
final InitializeStats iStats = iStatsBuilder.build();
assertThat(iStats.getStatusCode()).isEqualTo(TEST_STATUS_CODE);
@@ -192,6 +194,8 @@
assertThat(iStats.getDocumentStoreDataStatus()).isEqualTo(nativeDocumentStoreDataStatus);
assertThat(iStats.getDocumentCount()).isEqualTo(nativeNumDocuments);
assertThat(iStats.getSchemaTypeCount()).isEqualTo(nativeNumSchemaTypes);
+ assertThat(iStats.hasReset()).isTrue();
+ assertThat(iStats.getResetStatusCode()).isEqualTo(AppSearchResult.RESULT_INVALID_SCHEMA);
}
@Test
@@ -297,4 +301,28 @@
assertThat(sStats.getBackwardsIncompatibleTypeChangeCount())
.isEqualTo(backwardsIncompatibleTypeChangeCount);
}
+
+ @Test
+ public void testAppSearchStats_RemoveStats() {
+ int nativeLatencyMillis = 1;
+ @RemoveStats.DeleteType int deleteType = 2;
+ int documentDeletedCount = 3;
+
+ final RemoveStats rStats =
+ new RemoveStats.Builder(TEST_PACKAGE_NAME, TEST_DATA_BASE)
+ .setStatusCode(TEST_STATUS_CODE)
+ .setTotalLatencyMillis(TEST_TOTAL_LATENCY_MILLIS)
+ .setNativeLatencyMillis(nativeLatencyMillis)
+ .setDeleteType(deleteType)
+ .setDeletedDocumentCount(documentDeletedCount)
+ .build();
+
+ assertThat(rStats.getPackageName()).isEqualTo(TEST_PACKAGE_NAME);
+ assertThat(rStats.getDatabase()).isEqualTo(TEST_DATA_BASE);
+ assertThat(rStats.getStatusCode()).isEqualTo(TEST_STATUS_CODE);
+ assertThat(rStats.getTotalLatencyMillis()).isEqualTo(TEST_TOTAL_LATENCY_MILLIS);
+ assertThat(rStats.getNativeLatencyMillis()).isEqualTo(nativeLatencyMillis);
+ assertThat(rStats.getDeleteType()).isEqualTo(deleteType);
+ assertThat(rStats.getDeletedDocumentCount()).isEqualTo(documentDeletedCount);
+ }
}
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 217430c..e5bdafd 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
@@ -196,6 +196,12 @@
}
@Test
+ public void testCalculateHashCode_MD5_strIsNull() throws
+ NoSuchAlgorithmException, UnsupportedEncodingException {
+ assertThat(PlatformLogger.calculateHashCodeMd5(/*str=*/ null)).isEqualTo(-1);
+ }
+
+ @Test
public void testShouldLogForTypeLocked_trueWhenSampleRatioIsOne() {
final int samplingRatio = 1;
final String testPackageName = "packageName";
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 2270943..bfdf5af 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -6542,29 +6542,26 @@
final List<String> testPackages = new ArrayList<>();
testPackages.add("package_1");
testPackages.add("package_2");
-
- mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
+ mServiceContext.permissions.add(permission.MANAGE_DEVICE_ADMINS);
setDeviceOwner();
dpm.setUserControlDisabledPackages(admin1, testPackages);
- verify(getServices().packageManagerInternal).setDeviceOwnerProtectedPackages(testPackages);
-
+ verify(getServices().packageManagerInternal)
+ .setDeviceOwnerProtectedPackages(admin1.getPackageName(), testPackages);
assertThat(dpm.getUserControlDisabledPackages(admin1)).isEqualTo(testPackages);
}
@Test
- public void testSetUserControlDisabledPackages_failingAsPO() throws Exception {
+ public void testSetUserControlDisabledPackages_failingAsPO() {
final List<String> testPackages = new ArrayList<>();
testPackages.add("package_1");
testPackages.add("package_2");
-
- mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
+ mServiceContext.permissions.add(permission.MANAGE_DEVICE_ADMINS);
setAsProfileOwner(admin1);
assertExpectException(SecurityException.class, /* messageRegex= */ null,
() -> dpm.setUserControlDisabledPackages(admin1, testPackages));
-
assertExpectException(SecurityException.class, /* messageRegex= */ null,
() -> dpm.getUserControlDisabledPackages(admin1));
}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/OwnersTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/OwnersTest.java
index 39ca925d..02a8ae8 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/OwnersTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/OwnersTest.java
@@ -21,6 +21,8 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.verify;
+
import android.content.ComponentName;
import android.os.UserHandle;
import android.test.suitebuilder.annotation.SmallTest;
@@ -29,9 +31,14 @@
import com.android.server.devicepolicy.DevicePolicyManagerServiceTestable.OwnersTestable;
+import com.google.android.collect.Lists;
+
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.ArrayList;
+import java.util.List;
+
/**
* Tests for the DeviceOwner object that saves & loads device and policy owner information.
*
@@ -43,6 +50,9 @@
@RunWith(AndroidJUnit4.class)
public class OwnersTest extends DpmTestBase {
+ private static final List<String> DEVICE_OWNER_PROTECTED_PACKAGES =
+ Lists.newArrayList("package_1", "package_2");
+
@Test
public void testUpgrade01() throws Exception {
getServices().addUsers(10, 11, 20, 21);
@@ -71,6 +81,8 @@
assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL);
assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
DEVICE_OWNER_TYPE_DEFAULT);
+ assertThat(owners.getDeviceOwnerProtectedPackages(owners.getDeviceOwnerPackageName()))
+ .isEmpty();
assertThat(owners.getSystemUpdatePolicy()).isNull();
assertThat(owners.getProfileOwnerKeys()).isEmpty();
@@ -96,6 +108,8 @@
assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL);
assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
DEVICE_OWNER_TYPE_DEFAULT);
+ assertThat(owners.getDeviceOwnerProtectedPackages(owners.getDeviceOwnerPackageName()))
+ .isEmpty();
assertThat(owners.getSystemUpdatePolicy()).isNull();
assertThat(owners.getProfileOwnerKeys()).isEmpty();
@@ -136,6 +150,8 @@
assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_SYSTEM);
assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
DEVICE_OWNER_TYPE_DEFAULT);
+ assertThat(owners.getDeviceOwnerProtectedPackages(owners.getDeviceOwnerPackageName()))
+ .isEmpty();
assertThat(owners.getSystemUpdatePolicy()).isNull();
assertThat(owners.getProfileOwnerKeys()).isEmpty();
@@ -158,6 +174,8 @@
assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_SYSTEM);
assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
DEVICE_OWNER_TYPE_DEFAULT);
+ assertThat(owners.getDeviceOwnerProtectedPackages(owners.getDeviceOwnerPackageName()))
+ .isEmpty();
assertThat(owners.getSystemUpdatePolicy()).isNull();
assertThat(owners.getProfileOwnerKeys()).isEmpty();
@@ -198,6 +216,8 @@
assertThat(owners.getSystemUpdatePolicy()).isNull();
assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
DEVICE_OWNER_TYPE_DEFAULT);
+ assertThat(owners.getDeviceOwnerProtectedPackages(owners.getDeviceOwnerPackageName()))
+ .isEmpty();
assertThat(owners.getProfileOwnerKeys()).hasSize(2);
assertThat(owners.getProfileOwnerComponent(10))
@@ -228,6 +248,8 @@
assertThat(owners.getSystemUpdatePolicy()).isNull();
assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
DEVICE_OWNER_TYPE_DEFAULT);
+ assertThat(owners.getDeviceOwnerProtectedPackages(owners.getDeviceOwnerPackageName()))
+ .isEmpty();
assertThat(owners.getProfileOwnerKeys()).hasSize(2);
assertThat(owners.getProfileOwnerComponent(10))
@@ -282,6 +304,8 @@
assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_SYSTEM);
assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
DEVICE_OWNER_TYPE_DEFAULT);
+ assertThat(owners.getDeviceOwnerProtectedPackages(owners.getDeviceOwnerPackageName()))
+ .isEmpty();
assertThat(owners.getSystemUpdatePolicy()).isNotNull();
assertThat(owners.getSystemUpdatePolicy().getPolicyType()).isEqualTo(5);
@@ -316,6 +340,8 @@
assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_SYSTEM);
assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
DEVICE_OWNER_TYPE_DEFAULT);
+ assertThat(owners.getDeviceOwnerProtectedPackages(owners.getDeviceOwnerPackageName()))
+ .isEmpty();
assertThat(owners.getSystemUpdatePolicy()).isNotNull();
assertThat(owners.getSystemUpdatePolicy().getPolicyType()).isEqualTo(5);
@@ -344,6 +370,14 @@
DEVICE_OWNER_TYPE_FINANCED);
assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
DEVICE_OWNER_TYPE_FINANCED);
+
+ owners.setDeviceOwnerProtectedPackages(
+ owners.getDeviceOwnerPackageName(), DEVICE_OWNER_PROTECTED_PACKAGES);
+ assertThat(owners.getDeviceOwnerProtectedPackages(owners.getDeviceOwnerPackageName()))
+ .isEqualTo(DEVICE_OWNER_PROTECTED_PACKAGES);
+ verify(getServices().packageManagerInternal)
+ .setDeviceOwnerProtectedPackages(
+ owners.getDeviceOwnerPackageName(), DEVICE_OWNER_PROTECTED_PACKAGES);
}
{
@@ -353,6 +387,8 @@
assertThat(owners.hasDeviceOwner()).isTrue();
assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
DEVICE_OWNER_TYPE_FINANCED);
+ assertThat(owners.getDeviceOwnerProtectedPackages(owners.getDeviceOwnerPackageName()))
+ .isEqualTo(DEVICE_OWNER_PROTECTED_PACKAGES);
assertThat(owners.getDeviceOwnerUserRestrictionsNeedsMigration()).isFalse();
assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(10)).isTrue();
@@ -367,6 +403,14 @@
// The previous device owner type should persist.
assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
DEVICE_OWNER_TYPE_FINANCED);
+
+ owners.setDeviceOwnerProtectedPackages(
+ owners.getDeviceOwnerPackageName(), new ArrayList<>());
+ assertThat(owners.getDeviceOwnerProtectedPackages(owners.getDeviceOwnerPackageName()))
+ .isEmpty();
+ verify(getServices().packageManagerInternal)
+ .setDeviceOwnerProtectedPackages(
+ owners.getDeviceOwnerPackageName(), new ArrayList<>());
}
{
@@ -376,6 +420,8 @@
assertThat(owners.hasDeviceOwner()).isTrue();
assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
DEVICE_OWNER_TYPE_FINANCED);
+ assertThat(owners.getDeviceOwnerProtectedPackages(owners.getDeviceOwnerPackageName()))
+ .isEmpty();
assertThat(owners.getDeviceOwnerUserRestrictionsNeedsMigration()).isFalse();
assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(10)).isTrue();
@@ -414,6 +460,8 @@
assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL);
assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
DEVICE_OWNER_TYPE_DEFAULT);
+ assertThat(owners.getDeviceOwnerProtectedPackages(owners.getDeviceOwnerPackageName()))
+ .isEmpty();
assertThat(owners.getSystemUpdatePolicy()).isNull();
@@ -435,6 +483,8 @@
assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL);
assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
DEVICE_OWNER_TYPE_DEFAULT);
+ assertThat(owners.getDeviceOwnerProtectedPackages(owners.getDeviceOwnerPackageName()))
+ .isEmpty();
assertThat(owners.getSystemUpdatePolicy()).isNull();
@@ -474,6 +524,8 @@
assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL);
assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
DEVICE_OWNER_TYPE_DEFAULT);
+ assertThat(owners.getDeviceOwnerProtectedPackages(owners.getDeviceOwnerPackageName()))
+ .isEmpty();
assertThat(owners.getProfileOwnerKeys()).isEmpty();
assertThat(owners.getSystemUpdatePolicy()).isNotNull();
@@ -495,6 +547,8 @@
assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL);
assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
DEVICE_OWNER_TYPE_DEFAULT);
+ assertThat(owners.getDeviceOwnerProtectedPackages(owners.getDeviceOwnerPackageName()))
+ .isEmpty();
assertThat(owners.getProfileOwnerKeys()).isEmpty();
assertThat(owners.getSystemUpdatePolicy()).isNotNull();
@@ -525,6 +579,8 @@
assertThat(owners.getDeviceOwnerFile().exists()).isTrue();
assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
DEVICE_OWNER_TYPE_DEFAULT);
+ assertThat(owners.getDeviceOwnerProtectedPackages(owners.getDeviceOwnerPackageName()))
+ .isEmpty();
assertThat(owners.getProfileOwnerFile(10).exists()).isTrue();
assertThat(owners.getProfileOwnerFile(11).exists()).isTrue();
@@ -532,6 +588,13 @@
owners.setDeviceOwnerType(previousDeviceOwnerPackageName, DEVICE_OWNER_TYPE_FINANCED);
assertThat(owners.getDeviceOwnerType(previousDeviceOwnerPackageName)).isEqualTo(
DEVICE_OWNER_TYPE_FINANCED);
+ owners.setDeviceOwnerProtectedPackages(
+ previousDeviceOwnerPackageName, DEVICE_OWNER_PROTECTED_PACKAGES);
+ assertThat(owners.getDeviceOwnerProtectedPackages(previousDeviceOwnerPackageName))
+ .isEqualTo(DEVICE_OWNER_PROTECTED_PACKAGES);
+ verify(getServices().packageManagerInternal)
+ .setDeviceOwnerProtectedPackages(
+ owners.getDeviceOwnerPackageName(), DEVICE_OWNER_PROTECTED_PACKAGES);
// Then clear all information and save.
owners.clearDeviceOwner();
@@ -552,5 +615,10 @@
assertThat(owners.getDeviceOwnerType(previousDeviceOwnerPackageName)).isEqualTo(
DEVICE_OWNER_TYPE_DEFAULT);
+ assertThat(owners.getDeviceOwnerProtectedPackages(previousDeviceOwnerPackageName))
+ .isEmpty();
+ verify(getServices().packageManagerInternal)
+ .setDeviceOwnerProtectedPackages(
+ previousDeviceOwnerPackageName, new ArrayList<>());
}
}
diff --git a/services/tests/servicestests/src/com/android/server/graphics/fonts/UpdatableFontDirTest.java b/services/tests/servicestests/src/com/android/server/graphics/fonts/UpdatableFontDirTest.java
index 7003ef7..f9b8373 100644
--- a/services/tests/servicestests/src/com/android/server/graphics/fonts/UpdatableFontDirTest.java
+++ b/services/tests/servicestests/src/com/android/server/graphics/fonts/UpdatableFontDirTest.java
@@ -139,9 +139,11 @@
private File mUpdatableFontFilesDir;
private File mConfigFile;
private List<File> mPreinstalledFontDirs;
- private Supplier<Long> mCurrentTimeSupplier = () -> CURRENT_TIME;
- private Function<Map<String, File>, FontConfig> mConfigSupplier =
+ private final Supplier<Long> mCurrentTimeSupplier = () -> CURRENT_TIME;
+ private final Function<Map<String, File>, FontConfig> mConfigSupplier =
(map) -> SystemFonts.getSystemFontConfig(map, 0, 0);
+ private FakeFontFileParser mParser;
+ private FakeFsverityUtil mFakeFsverityUtil;
@SuppressWarnings("ResultOfMethodCallIgnored")
@Before
@@ -159,6 +161,8 @@
dir.mkdir();
}
mConfigFile = new File(mCacheDir, "config.xml");
+ mParser = new FakeFontFileParser();
+ mFakeFsverityUtil = new FakeFsverityUtil();
}
@After
@@ -169,13 +173,11 @@
@Test
public void construct() throws Exception {
long expectedModifiedDate = CURRENT_TIME / 2;
- FakeFontFileParser parser = new FakeFontFileParser();
- FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
PersistentSystemFontConfig.Config config = new PersistentSystemFontConfig.Config();
config.lastModifiedMillis = expectedModifiedDate;
writeConfig(config, mConfigFile);
UpdatableFontDir dirForPreparation = new UpdatableFontDir(
- mUpdatableFontFilesDir, parser, fakeFsverityUtil,
+ mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
dirForPreparation.loadFontFileMap();
assertThat(dirForPreparation.getSystemFontConfig().getLastModifiedTimeMillis())
@@ -198,13 +200,13 @@
.isNotEqualTo(expectedModifiedDate);
UpdatableFontDir dir = new UpdatableFontDir(
- mUpdatableFontFilesDir, parser, fakeFsverityUtil,
+ mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
dir.loadFontFileMap();
assertThat(dir.getPostScriptMap()).containsKey("foo");
- assertThat(parser.getRevision(dir.getPostScriptMap().get("foo"))).isEqualTo(3);
+ assertThat(mParser.getRevision(dir.getPostScriptMap().get("foo"))).isEqualTo(3);
assertThat(dir.getPostScriptMap()).containsKey("bar");
- assertThat(parser.getRevision(dir.getPostScriptMap().get("bar"))).isEqualTo(4);
+ assertThat(mParser.getRevision(dir.getPostScriptMap().get("bar"))).isEqualTo(4);
// Outdated font dir should be deleted.
assertThat(mUpdatableFontFilesDir.list()).hasLength(2);
assertNamedFamilyExists(dir.getSystemFontConfig(), "foobar");
@@ -219,10 +221,8 @@
@Test
public void construct_empty() {
- FakeFontFileParser parser = new FakeFontFileParser();
- FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
UpdatableFontDir dir = new UpdatableFontDir(
- mUpdatableFontFilesDir, parser, fakeFsverityUtil,
+ mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
dir.loadFontFileMap();
assertThat(dir.getPostScriptMap()).isEmpty();
@@ -231,10 +231,8 @@
@Test
public void construct_missingFsverity() throws Exception {
- FakeFontFileParser parser = new FakeFontFileParser();
- FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
UpdatableFontDir dirForPreparation = new UpdatableFontDir(
- mUpdatableFontFilesDir, parser, fakeFsverityUtil,
+ mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
dirForPreparation.loadFontFileMap();
dirForPreparation.update(Arrays.asList(
@@ -249,10 +247,10 @@
// Four font dirs are created.
assertThat(mUpdatableFontFilesDir.list()).hasLength(4);
- fakeFsverityUtil.remove(
+ mFakeFsverityUtil.remove(
dirForPreparation.getPostScriptMap().get("foo").getAbsolutePath());
UpdatableFontDir dir = new UpdatableFontDir(
- mUpdatableFontFilesDir, parser, fakeFsverityUtil,
+ mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
dir.loadFontFileMap();
assertThat(dir.getPostScriptMap()).isEmpty();
@@ -263,10 +261,8 @@
@Test
public void construct_fontNameMismatch() throws Exception {
- FakeFontFileParser parser = new FakeFontFileParser();
- FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
UpdatableFontDir dirForPreparation = new UpdatableFontDir(
- mUpdatableFontFilesDir, parser, fakeFsverityUtil,
+ mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
dirForPreparation.loadFontFileMap();
dirForPreparation.update(Arrays.asList(
@@ -285,7 +281,7 @@
FileUtils.stringToFile(dirForPreparation.getPostScriptMap().get("foo"), "bar,4");
UpdatableFontDir dir = new UpdatableFontDir(
- mUpdatableFontFilesDir, parser, fakeFsverityUtil,
+ mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
dir.loadFontFileMap();
assertThat(dir.getPostScriptMap()).isEmpty();
@@ -296,8 +292,6 @@
@Test
public void construct_olderThanPreinstalledFont() throws Exception {
- FakeFontFileParser parser = new FakeFontFileParser();
- FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
Function<Map<String, File>, FontConfig> configSupplier = (map) -> {
FontConfig.Font fooFont = new FontConfig.Font(
new File(mPreinstalledFontDirs.get(0), "foo.ttf"), null, "foo",
@@ -314,7 +308,7 @@
};
UpdatableFontDir dirForPreparation = new UpdatableFontDir(
- mUpdatableFontFilesDir, parser, fakeFsverityUtil,
+ mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
mConfigFile, mCurrentTimeSupplier, configSupplier);
dirForPreparation.loadFontFileMap();
dirForPreparation.update(Arrays.asList(
@@ -334,14 +328,14 @@
FileUtils.stringToFile(new File(mPreinstalledFontDirs.get(1), "bar.ttf"), "bar,1,bar");
FileUtils.stringToFile(new File(mPreinstalledFontDirs.get(1), "bar.ttf"), "bar,2,bar");
UpdatableFontDir dir = new UpdatableFontDir(
- mUpdatableFontFilesDir, parser, fakeFsverityUtil,
+ mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
mConfigFile, mCurrentTimeSupplier, configSupplier);
dir.loadFontFileMap();
// For foo.ttf, preinstalled font (revision 5) should be used.
assertThat(dir.getPostScriptMap()).doesNotContainKey("foo");
// For bar.ttf, updated font (revision 4) should be used.
assertThat(dir.getPostScriptMap()).containsKey("bar");
- assertThat(parser.getRevision(dir.getPostScriptMap().get("bar"))).isEqualTo(4);
+ assertThat(mParser.getRevision(dir.getPostScriptMap().get("bar"))).isEqualTo(4);
// Outdated font dir should be deleted.
// We don't delete bar.ttf in this case, because it's normal that OTA updates preinstalled
// fonts.
@@ -352,10 +346,8 @@
@Test
public void construct_failedToLoadConfig() throws Exception {
- FakeFontFileParser parser = new FakeFontFileParser();
- FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
UpdatableFontDir dir = new UpdatableFontDir(
- mUpdatableFontFilesDir, parser, fakeFsverityUtil,
+ mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
new File("/dev/null"), mCurrentTimeSupplier, mConfigSupplier);
dir.loadFontFileMap();
assertThat(dir.getPostScriptMap()).isEmpty();
@@ -364,10 +356,8 @@
@Test
public void construct_afterBatchFailure() throws Exception {
- FakeFontFileParser parser = new FakeFontFileParser();
- FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
UpdatableFontDir dirForPreparation = new UpdatableFontDir(
- mUpdatableFontFilesDir, parser, fakeFsverityUtil,
+ mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
dirForPreparation.loadFontFileMap();
dirForPreparation.update(Arrays.asList(
@@ -389,12 +379,12 @@
}
UpdatableFontDir dir = new UpdatableFontDir(
- mUpdatableFontFilesDir, parser, fakeFsverityUtil,
+ mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
dir.loadFontFileMap();
// The state should be rolled back as a whole if one of the update requests fail.
assertThat(dir.getPostScriptMap()).containsKey("foo");
- assertThat(parser.getRevision(dir.getPostScriptMap().get("foo"))).isEqualTo(1);
+ assertThat(mParser.getRevision(dir.getPostScriptMap().get("foo"))).isEqualTo(1);
assertThat(dir.getFontFamilyMap()).containsKey("foobar");
FontConfig.FontFamily foobar = dir.getFontFamilyMap().get("foobar");
assertThat(foobar.getFontList()).hasSize(1);
@@ -404,10 +394,8 @@
@Test
public void loadFontFileMap_twice() throws Exception {
- FakeFontFileParser parser = new FakeFontFileParser();
- FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
UpdatableFontDir dir = new UpdatableFontDir(
- mUpdatableFontFilesDir, parser, fakeFsverityUtil,
+ mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
dir.loadFontFileMap();
dir.update(Collections.singletonList(newFontUpdateRequest("test.ttf,1,test",
@@ -420,17 +408,15 @@
@Test
public void installFontFile() throws Exception {
- FakeFontFileParser parser = new FakeFontFileParser();
- FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
UpdatableFontDir dir = new UpdatableFontDir(
- mUpdatableFontFilesDir, parser, fakeFsverityUtil,
+ mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
dir.loadFontFileMap();
dir.update(Collections.singletonList(newFontUpdateRequest("test.ttf,1,test",
GOOD_SIGNATURE)));
assertThat(dir.getPostScriptMap()).containsKey("test");
- assertThat(parser.getRevision(dir.getPostScriptMap().get("test"))).isEqualTo(1);
+ assertThat(mParser.getRevision(dir.getPostScriptMap().get("test"))).isEqualTo(1);
File fontFile = dir.getPostScriptMap().get("test");
assertThat(Os.stat(fontFile.getAbsolutePath()).st_mode & 0777).isEqualTo(0644);
File fontDir = fontFile.getParentFile();
@@ -439,10 +425,8 @@
@Test
public void installFontFile_upgrade() throws Exception {
- FakeFontFileParser parser = new FakeFontFileParser();
- FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
UpdatableFontDir dir = new UpdatableFontDir(
- mUpdatableFontFilesDir, parser, fakeFsverityUtil,
+ mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
dir.loadFontFileMap();
@@ -452,10 +436,10 @@
dir.update(Collections.singletonList(newFontUpdateRequest("test.ttf,2,test",
GOOD_SIGNATURE)));
assertThat(dir.getPostScriptMap()).containsKey("test");
- assertThat(parser.getRevision(dir.getPostScriptMap().get("test"))).isEqualTo(2);
+ assertThat(mParser.getRevision(dir.getPostScriptMap().get("test"))).isEqualTo(2);
assertThat(mapBeforeUpgrade).containsKey("test");
assertWithMessage("Older fonts should not be deleted until next loadFontFileMap")
- .that(parser.getRevision(mapBeforeUpgrade.get("test"))).isEqualTo(1);
+ .that(mParser.getRevision(mapBeforeUpgrade.get("test"))).isEqualTo(1);
// Check that updatedFontDirs is pruned.
assertWithMessage("config.updatedFontDirs should only list latest active dirs")
.that(readConfig(mConfigFile).updatedFontDirs)
@@ -464,15 +448,13 @@
@Test
public void installFontFile_systemFontHasPSNameDifferentFromFileName() throws Exception {
- FakeFontFileParser parser = new FakeFontFileParser();
- FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
// Setup the environment that the system installed font file named "foo.ttf" has PostScript
// name "bar".
File file = new File(mPreinstalledFontDirs.get(0), "foo.ttf");
FileUtils.stringToFile(file, "foo.ttf,1,bar");
UpdatableFontDir dir = new UpdatableFontDir(
- mUpdatableFontFilesDir, parser, fakeFsverityUtil,
+ mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
mConfigFile, mCurrentTimeSupplier, (map) -> {
FontConfig.Font font = new FontConfig.Font(
file, null, "bar", new FontStyle(400, FontStyle.FONT_SLANT_UPRIGHT),
@@ -489,7 +471,7 @@
GOOD_SIGNATURE)));
assertThat(dir.getPostScriptMap()).containsKey("bar");
assertThat(dir.getPostScriptMap().size()).isEqualTo(1);
- assertThat(parser.getRevision(dir.getPostScriptMap().get("bar"))).isEqualTo(2);
+ assertThat(mParser.getRevision(dir.getPostScriptMap().get("bar"))).isEqualTo(2);
File fontFile = dir.getPostScriptMap().get("bar");
assertThat(Os.stat(fontFile.getAbsolutePath()).st_mode & 0777).isEqualTo(0644);
File fontDir = fontFile.getParentFile();
@@ -498,10 +480,8 @@
@Test
public void installFontFile_sameVersion() throws Exception {
- FakeFontFileParser parser = new FakeFontFileParser();
- FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
UpdatableFontDir dir = new UpdatableFontDir(
- mUpdatableFontFilesDir, parser, fakeFsverityUtil,
+ mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
dir.loadFontFileMap();
@@ -510,15 +490,13 @@
dir.update(Collections.singletonList(newFontUpdateRequest("test.ttf,1,test",
GOOD_SIGNATURE)));
assertThat(dir.getPostScriptMap()).containsKey("test");
- assertThat(parser.getRevision(dir.getPostScriptMap().get("test"))).isEqualTo(1);
+ assertThat(mParser.getRevision(dir.getPostScriptMap().get("test"))).isEqualTo(1);
}
@Test
public void installFontFile_downgrade() throws Exception {
- FakeFontFileParser parser = new FakeFontFileParser();
- FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
UpdatableFontDir dir = new UpdatableFontDir(
- mUpdatableFontFilesDir, parser, fakeFsverityUtil,
+ mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
dir.loadFontFileMap();
@@ -533,7 +511,7 @@
}
assertThat(dir.getPostScriptMap()).containsKey("test");
assertWithMessage("Font should not be downgraded to an older revision")
- .that(parser.getRevision(dir.getPostScriptMap().get("test"))).isEqualTo(2);
+ .that(mParser.getRevision(dir.getPostScriptMap().get("test"))).isEqualTo(2);
// Check that updatedFontDirs is not updated.
assertWithMessage("config.updatedFontDirs should only list latest active dirs")
.that(readConfig(mConfigFile).updatedFontDirs)
@@ -542,10 +520,8 @@
@Test
public void installFontFile_multiple() throws Exception {
- FakeFontFileParser parser = new FakeFontFileParser();
- FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
UpdatableFontDir dir = new UpdatableFontDir(
- mUpdatableFontFilesDir, parser, fakeFsverityUtil,
+ mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
dir.loadFontFileMap();
@@ -554,17 +530,15 @@
dir.update(Collections.singletonList(newFontUpdateRequest("bar.ttf,2,bar",
GOOD_SIGNATURE)));
assertThat(dir.getPostScriptMap()).containsKey("foo");
- assertThat(parser.getRevision(dir.getPostScriptMap().get("foo"))).isEqualTo(1);
+ assertThat(mParser.getRevision(dir.getPostScriptMap().get("foo"))).isEqualTo(1);
assertThat(dir.getPostScriptMap()).containsKey("bar");
- assertThat(parser.getRevision(dir.getPostScriptMap().get("bar"))).isEqualTo(2);
+ assertThat(mParser.getRevision(dir.getPostScriptMap().get("bar"))).isEqualTo(2);
}
@Test
public void installFontFile_batch() throws Exception {
- FakeFontFileParser parser = new FakeFontFileParser();
- FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
UpdatableFontDir dir = new UpdatableFontDir(
- mUpdatableFontFilesDir, parser, fakeFsverityUtil,
+ mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
dir.loadFontFileMap();
@@ -572,17 +546,15 @@
newFontUpdateRequest("foo.ttf,1,foo", GOOD_SIGNATURE),
newFontUpdateRequest("bar.ttf,2,bar", GOOD_SIGNATURE)));
assertThat(dir.getPostScriptMap()).containsKey("foo");
- assertThat(parser.getRevision(dir.getPostScriptMap().get("foo"))).isEqualTo(1);
+ assertThat(mParser.getRevision(dir.getPostScriptMap().get("foo"))).isEqualTo(1);
assertThat(dir.getPostScriptMap()).containsKey("bar");
- assertThat(parser.getRevision(dir.getPostScriptMap().get("bar"))).isEqualTo(2);
+ assertThat(mParser.getRevision(dir.getPostScriptMap().get("bar"))).isEqualTo(2);
}
@Test
public void installFontFile_invalidSignature() throws Exception {
- FakeFontFileParser parser = new FakeFontFileParser();
- FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
UpdatableFontDir dir = new UpdatableFontDir(
- mUpdatableFontFilesDir, parser, fakeFsverityUtil,
+ mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
dir.loadFontFileMap();
@@ -600,46 +572,40 @@
@Test
public void installFontFile_preinstalled_upgrade() throws Exception {
- FakeFontFileParser parser = new FakeFontFileParser();
- FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
FileUtils.stringToFile(new File(mPreinstalledFontDirs.get(0), "test.ttf"),
"test.ttf,1,test");
UpdatableFontDir dir = new UpdatableFontDir(
- mUpdatableFontFilesDir, parser, fakeFsverityUtil,
+ mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
dir.loadFontFileMap();
dir.update(Collections.singletonList(newFontUpdateRequest("test.ttf,2,test",
GOOD_SIGNATURE)));
assertThat(dir.getPostScriptMap()).containsKey("test");
- assertThat(parser.getRevision(dir.getPostScriptMap().get("test"))).isEqualTo(2);
+ assertThat(mParser.getRevision(dir.getPostScriptMap().get("test"))).isEqualTo(2);
}
@Test
public void installFontFile_preinstalled_sameVersion() throws Exception {
- FakeFontFileParser parser = new FakeFontFileParser();
- FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
FileUtils.stringToFile(new File(mPreinstalledFontDirs.get(0), "test.ttf"),
"test.ttf,1,test");
UpdatableFontDir dir = new UpdatableFontDir(
- mUpdatableFontFilesDir, parser, fakeFsverityUtil,
+ mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
dir.loadFontFileMap();
dir.update(Collections.singletonList(newFontUpdateRequest("test.ttf,1,test",
GOOD_SIGNATURE)));
assertThat(dir.getPostScriptMap()).containsKey("test");
- assertThat(parser.getRevision(dir.getPostScriptMap().get("test"))).isEqualTo(1);
+ assertThat(mParser.getRevision(dir.getPostScriptMap().get("test"))).isEqualTo(1);
}
@Test
public void installFontFile_preinstalled_downgrade() throws Exception {
- FakeFontFileParser parser = new FakeFontFileParser();
- FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
File file = new File(mPreinstalledFontDirs.get(0), "test.ttf");
FileUtils.stringToFile(file, "test.ttf,2,test");
UpdatableFontDir dir = new UpdatableFontDir(
- mUpdatableFontFilesDir, parser, fakeFsverityUtil,
+ mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
mConfigFile, mCurrentTimeSupplier, (map) -> {
FontConfig.Font font = new FontConfig.Font(
file, null, "test", new FontStyle(400, FontStyle.FONT_SLANT_UPRIGHT), 0, null,
@@ -664,8 +630,6 @@
@Test
public void installFontFile_failedToWriteConfigXml() throws Exception {
long expectedModifiedDate = 1234567890;
- FakeFontFileParser parser = new FakeFontFileParser();
- FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
FileUtils.stringToFile(new File(mPreinstalledFontDirs.get(0), "test.ttf"),
"test.ttf,1,test");
@@ -680,7 +644,7 @@
assertThat(readonlyDir.setWritable(false, false)).isTrue();
try {
UpdatableFontDir dir = new UpdatableFontDir(
- mUpdatableFontFilesDir, parser, fakeFsverityUtil,
+ mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
readonlyFile, mCurrentTimeSupplier, mConfigSupplier);
dir.loadFontFileMap();
@@ -702,7 +666,6 @@
@Test
public void installFontFile_failedToParsePostScript() throws Exception {
- FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
UpdatableFontDir dir = new UpdatableFontDir(
mUpdatableFontFilesDir,
new UpdatableFontDir.FontFileParser() {
@@ -725,7 +688,7 @@
@Override
public void tryToCreateTypeface(File file) throws IOException {
}
- }, fakeFsverityUtil, mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
+ }, mFakeFsverityUtil, mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
dir.loadFontFileMap();
try {
@@ -741,7 +704,6 @@
@Test
public void installFontFile_failedToParsePostScriptName_invalidFont() throws Exception {
- FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
UpdatableFontDir dir = new UpdatableFontDir(
mUpdatableFontFilesDir,
new UpdatableFontDir.FontFileParser() {
@@ -763,7 +725,7 @@
@Override
public void tryToCreateTypeface(File file) throws IOException {
}
- }, fakeFsverityUtil, mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
+ }, mFakeFsverityUtil, mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
dir.loadFontFileMap();
try {
@@ -779,31 +741,29 @@
@Test
public void installFontFile_failedToCreateTypeface() throws Exception {
- FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
- FakeFontFileParser parser = new FakeFontFileParser();
UpdatableFontDir dir = new UpdatableFontDir(
mUpdatableFontFilesDir,
new UpdatableFontDir.FontFileParser() {
@Override
public String getPostScriptName(File file) throws IOException {
- return parser.getPostScriptName(file);
+ return mParser.getPostScriptName(file);
}
@Override
public String buildFontFileName(File file) throws IOException {
- return parser.buildFontFileName(file);
+ return mParser.buildFontFileName(file);
}
@Override
public long getRevision(File file) throws IOException {
- return parser.getRevision(file);
+ return mParser.getRevision(file);
}
@Override
public void tryToCreateTypeface(File file) throws IOException {
throw new IOException();
}
- }, fakeFsverityUtil, mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
+ }, mFakeFsverityUtil, mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
dir.loadFontFileMap();
try {
@@ -820,16 +780,15 @@
@Test
public void installFontFile_renameToPsNameFailure() throws Exception {
UpdatableFontDir.FsverityUtil fakeFsverityUtil = new UpdatableFontDir.FsverityUtil() {
- private final FakeFsverityUtil mFake = new FakeFsverityUtil();
@Override
public boolean hasFsverity(String path) {
- return mFake.hasFsverity(path);
+ return mFakeFsverityUtil.hasFsverity(path);
}
@Override
public void setUpFsverity(String path, byte[] pkcs7Signature) throws IOException {
- mFake.setUpFsverity(path, pkcs7Signature);
+ mFakeFsverityUtil.setUpFsverity(path, pkcs7Signature);
}
@Override
@@ -837,9 +796,8 @@
return false;
}
};
- FakeFontFileParser parser = new FakeFontFileParser();
UpdatableFontDir dir = new UpdatableFontDir(
- mUpdatableFontFilesDir, parser, fakeFsverityUtil,
+ mUpdatableFontFilesDir, mParser, fakeFsverityUtil,
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
dir.loadFontFileMap();
@@ -856,10 +814,8 @@
@Test
public void installFontFile_batchFailure() throws Exception {
- FakeFontFileParser parser = new FakeFontFileParser();
- FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
UpdatableFontDir dir = new UpdatableFontDir(
- mUpdatableFontFilesDir, parser, fakeFsverityUtil,
+ mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
dir.loadFontFileMap();
@@ -875,15 +831,13 @@
}
// The state should be rolled back as a whole if one of the update requests fail.
assertThat(dir.getPostScriptMap()).containsKey("foo");
- assertThat(parser.getRevision(dir.getPostScriptMap().get("foo"))).isEqualTo(1);
+ assertThat(mParser.getRevision(dir.getPostScriptMap().get("foo"))).isEqualTo(1);
}
@Test
public void addFontFamily() throws Exception {
- FakeFontFileParser parser = new FakeFontFileParser();
- FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
UpdatableFontDir dir = new UpdatableFontDir(
- mUpdatableFontFilesDir, parser, fakeFsverityUtil,
+ mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
dir.loadFontFileMap();
@@ -902,10 +856,8 @@
@Test
public void addFontFamily_noName() throws Exception {
- FakeFontFileParser parser = new FakeFontFileParser();
- FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
UpdatableFontDir dir = new UpdatableFontDir(
- mUpdatableFontFilesDir, parser, fakeFsverityUtil,
+ mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
dir.loadFontFileMap();
@@ -924,10 +876,8 @@
@Test
public void addFontFamily_fontNotAvailable() throws Exception {
- FakeFontFileParser parser = new FakeFontFileParser();
- FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
UpdatableFontDir dir = new UpdatableFontDir(
- mUpdatableFontFilesDir, parser, fakeFsverityUtil,
+ mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
dir.loadFontFileMap();
@@ -944,10 +894,8 @@
@Test
public void getSystemFontConfig() throws Exception {
- FakeFontFileParser parser = new FakeFontFileParser();
- FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
UpdatableFontDir dir = new UpdatableFontDir(
- mUpdatableFontFilesDir, parser, fakeFsverityUtil,
+ mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
dir.loadFontFileMap();
// We assume we have monospace.
@@ -976,10 +924,8 @@
@Test
public void getSystemFontConfig_preserveFirstFontFamily() throws Exception {
- FakeFontFileParser parser = new FakeFontFileParser();
- FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
UpdatableFontDir dir = new UpdatableFontDir(
- mUpdatableFontFilesDir, parser, fakeFsverityUtil,
+ mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
dir.loadFontFileMap();
assertThat(dir.getSystemFontConfig().getFontFamilies()).isNotEmpty();
@@ -1001,6 +947,24 @@
assertThat(updated).isNotEqualTo(firstFontFamily);
}
+ @Test
+ public void deleteAllFiles() throws Exception {
+ FakeFontFileParser parser = new FakeFontFileParser();
+ FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
+ UpdatableFontDir dirForPreparation = new UpdatableFontDir(
+ mUpdatableFontFilesDir, parser, fakeFsverityUtil,
+ mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
+ dirForPreparation.loadFontFileMap();
+ dirForPreparation.update(Collections.singletonList(
+ newFontUpdateRequest("foo.ttf,1,foo", GOOD_SIGNATURE)));
+ assertThat(mConfigFile.exists()).isTrue();
+ assertThat(mUpdatableFontFilesDir.list()).hasLength(1);
+
+ UpdatableFontDir.deleteAllFiles(mUpdatableFontFilesDir, mConfigFile);
+ assertThat(mConfigFile.exists()).isFalse();
+ assertThat(mUpdatableFontFilesDir.list()).hasLength(0);
+ }
+
private FontUpdateRequest newFontUpdateRequest(String content, String signature)
throws Exception {
File file = File.createTempFile("font", "ttf", mCacheDir);
@@ -1011,12 +975,12 @@
}
private static FontUpdateRequest newAddFontFamilyRequest(String xml) throws Exception {
- XmlPullParser parser = Xml.newPullParser();
+ XmlPullParser mParser = Xml.newPullParser();
ByteArrayInputStream is = new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8));
- parser.setInput(is, "UTF-8");
- parser.nextTag();
+ mParser.setInput(is, "UTF-8");
+ mParser.nextTag();
- FontConfig.FontFamily fontFamily = FontListParser.readFamily(parser, "", null, true);
+ FontConfig.FontFamily fontFamily = FontListParser.readFamily(mParser, "", null, true);
List<FontUpdateRequest.Font> fonts = new ArrayList<>();
for (FontConfig.Font font : fontFamily.getFontList()) {
String name = font.getFile().getName();
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
index 5fbf8de..524ad62 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
@@ -137,6 +137,11 @@
}
@Override
+ boolean isPowerStandbyOrTransient() {
+ return false;
+ }
+
+ @Override
protected PowerManager getPowerManager() {
return new PowerManager(context, mIPowerManagerMock,
mIThermalServiceMock, new Handler(mMyLooper));
@@ -1335,6 +1340,22 @@
}
@Test
+ public void handleSetStreamPath_Dreaming() throws RemoteException {
+ when(mIPowerManagerMock.isInteractive()).thenReturn(true);
+
+ mWokenUp = false;
+
+ HdmiCecMessage message =
+ HdmiCecMessageBuilder.buildSetStreamPath(ADDR_TV,
+ mPlaybackPhysicalAddress);
+
+ assertThat(mHdmiCecLocalDevicePlayback.handleSetStreamPath(message))
+ .isEqualTo(Constants.HANDLED);
+ mTestLooper.dispatchAll();
+ assertThat(mWokenUp).isTrue();
+ }
+
+ @Test
public void handleSetStreamPath_otherDevice_None() {
mHdmiCecLocalDevicePlayback.mService.getHdmiCecConfig().setStringValue(
HdmiControlManager.CEC_SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST,
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
index bcf30a2..0cf212c 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
@@ -17,6 +17,7 @@
import static android.hardware.hdmi.HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM;
import static android.hardware.hdmi.HdmiDeviceInfo.DEVICE_PLAYBACK;
+import static android.hardware.hdmi.HdmiDeviceInfo.DEVICE_TV;
import static com.android.server.SystemService.PHASE_BOOT_COMPLETED;
import static com.android.server.SystemService.PHASE_SYSTEM_SERVICES_READY;
@@ -47,6 +48,7 @@
import android.os.RemoteException;
import android.os.test.TestLooper;
import android.platform.test.annotations.Presubmit;
+import android.sysprop.HdmiProperties;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
@@ -828,4 +830,71 @@
assertThat(mHdmiControlServiceSpy.dispatchMessageToLocalDevice(message))
.isEqualTo(Constants.ABORT_REFUSED);
}
+
+ @Test
+ public void readDeviceTypes_readsIntegerDeviceTypes() {
+ doReturn(Arrays.asList(new Integer[]{DEVICE_PLAYBACK, DEVICE_AUDIO_SYSTEM}))
+ .when(mHdmiControlServiceSpy).getDeviceTypes();
+ doReturn(Arrays.asList(new HdmiProperties.cec_device_types_values[]{}))
+ .when(mHdmiControlServiceSpy).getCecDeviceTypes();
+
+ assertThat(mHdmiControlServiceSpy.readDeviceTypes())
+ .containsExactly(DEVICE_PLAYBACK, DEVICE_AUDIO_SYSTEM);
+ }
+
+ @Test
+ public void readDeviceTypes_readsEnumDeviceTypes() {
+ doReturn(Arrays.asList(new Integer[]{})).when(mHdmiControlServiceSpy).getDeviceTypes();
+ doReturn(Arrays.asList(
+ new HdmiProperties.cec_device_types_values[]{
+ HdmiProperties.cec_device_types_values.PLAYBACK_DEVICE,
+ HdmiProperties.cec_device_types_values.AUDIO_SYSTEM
+ }))
+ .when(mHdmiControlServiceSpy).getCecDeviceTypes();
+
+ assertThat(mHdmiControlServiceSpy.readDeviceTypes())
+ .containsExactly(DEVICE_PLAYBACK, DEVICE_AUDIO_SYSTEM);
+ }
+
+ @Test
+ public void readDeviceTypes_readsEnumOverIntegerDeviceTypes() {
+ doReturn(Arrays.asList(new Integer[]{DEVICE_TV}))
+ .when(mHdmiControlServiceSpy).getDeviceTypes();
+ doReturn(Arrays.asList(
+ new HdmiProperties.cec_device_types_values[]{
+ HdmiProperties.cec_device_types_values.PLAYBACK_DEVICE,
+ HdmiProperties.cec_device_types_values.AUDIO_SYSTEM
+ }))
+ .when(mHdmiControlServiceSpy).getCecDeviceTypes();
+
+ assertThat(mHdmiControlServiceSpy.readDeviceTypes())
+ .containsExactly(DEVICE_PLAYBACK, DEVICE_AUDIO_SYSTEM);
+ }
+
+ @Test
+ public void readDeviceTypes_doesNotReadNullEnumDeviceType() {
+ doReturn(Arrays.asList(new Integer[]{})).when(mHdmiControlServiceSpy).getDeviceTypes();
+ doReturn(Arrays.asList(
+ new HdmiProperties.cec_device_types_values[]{
+ HdmiProperties.cec_device_types_values.PLAYBACK_DEVICE,
+ HdmiProperties.cec_device_types_values.AUDIO_SYSTEM,
+ null
+ }))
+ .when(mHdmiControlServiceSpy).getCecDeviceTypes();
+
+ assertThat(mHdmiControlServiceSpy.readDeviceTypes())
+ .containsExactly(DEVICE_PLAYBACK, DEVICE_AUDIO_SYSTEM);
+ }
+
+ @Test
+ public void readDeviceTypes_doesNotReadNullIntegerDeviceType() {
+ doReturn(Arrays.asList(new Integer[]{DEVICE_PLAYBACK, DEVICE_AUDIO_SYSTEM, null}))
+ .when(mHdmiControlServiceSpy).getDeviceTypes();
+ doReturn(Arrays.asList(new HdmiProperties.cec_device_types_values[]{}))
+ .when(mHdmiControlServiceSpy).getCecDeviceTypes();
+
+ assertThat(mHdmiControlServiceSpy.readDeviceTypes())
+ .containsExactly(DEVICE_PLAYBACK, DEVICE_AUDIO_SYSTEM);
+ }
+
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index 4a09cf8..b2ddbf0 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -661,7 +661,8 @@
public void setSchema(String packageName, String databaseName, List<Bundle> schemaBundles,
List<String> schemasNotPlatformSurfaceable,
Map<String, List<Bundle>> schemasPackageAccessibleBundles, boolean forceOverride,
- int userId, int version, IAppSearchResultCallback callback) throws RemoteException {
+ int userId, int version, long binderCallStartTimeMillis,
+ IAppSearchResultCallback callback) throws RemoteException {
for (Map.Entry<String, List<Bundle>> entry :
schemasPackageAccessibleBundles.entrySet()) {
final String key = entry.getKey();
@@ -721,6 +722,7 @@
@Override
public void getDocuments(String packageName, String databaseName, String namespace,
List<String> ids, Map<String, List<String>> typePropertyPaths, int userId,
+ long binderCallStartTimeMillis,
IAppSearchBatchResultCallback callback) throws RemoteException {
final AppSearchBatchResult.Builder<String, Bundle> builder =
new AppSearchBatchResult.Builder<>();
@@ -746,7 +748,8 @@
@Override
public void query(String packageName, String databaseName, String queryExpression,
- Bundle searchSpecBundle, int userId, IAppSearchResultCallback callback)
+ Bundle searchSpecBundle, int userId, long binderCallStartTimeMillis,
+ IAppSearchResultCallback callback)
throws RemoteException {
final String key = getKey(userId, databaseName);
if (!mDocumentMap.containsKey(key)) {
@@ -776,7 +779,8 @@
@Override
public void globalQuery(String packageName, String queryExpression, Bundle searchSpecBundle,
- int userId, IAppSearchResultCallback callback) throws RemoteException {
+ int userId, long binderCallStartTimeMillis, IAppSearchResultCallback callback)
+ throws RemoteException {
ignore(callback);
}
@@ -820,7 +824,8 @@
@Override
public void removeByDocumentId(String packageName, String databaseName, String namespace,
- List<String> ids, int userId, IAppSearchBatchResultCallback callback)
+ List<String> ids, int userId, long binderCallStartTimeMillis,
+ IAppSearchBatchResultCallback callback)
throws RemoteException {
final AppSearchBatchResult.Builder<String, Void> builder =
new AppSearchBatchResult.Builder<>();
@@ -847,7 +852,8 @@
@Override
public void removeByQuery(String packageName, String databaseName, String queryExpression,
- Bundle searchSpecBundle, int userId, IAppSearchResultCallback callback)
+ Bundle searchSpecBundle, int userId, long binderCallStartTimeMillis,
+ IAppSearchResultCallback callback)
throws RemoteException {
final String key = getKey(userId, databaseName);
if (!mDocumentMap.containsKey(key)) {
@@ -867,12 +873,14 @@
}
@Override
- public void persistToDisk(int userId) throws RemoteException {
+ public void persistToDisk(int userId, long binderCallStartTimeMillis)
+ throws RemoteException {
}
@Override
- public void initialize(int userId, IAppSearchResultCallback callback)
+ public void initialize(int userId, long binderCallStartTimeMillis,
+ IAppSearchResultCallback callback)
throws RemoteException {
ignore(callback);
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/CompatibilityModeTest.java b/services/tests/servicestests/src/com/android/server/pm/CompatibilityModeTest.java
new file mode 100644
index 0000000..94ac9be
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/pm/CompatibilityModeTest.java
@@ -0,0 +1,234 @@
+/*
+ * 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.pm;
+
+import static android.content.pm.ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS;
+import static android.content.pm.ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS;
+import static android.content.pm.ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS;
+import static android.content.pm.ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES;
+import static android.content.pm.ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS;
+import static android.content.pm.ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageParser;
+import android.content.pm.PackageUserState;
+import android.content.pm.parsing.PackageInfoWithoutStateUtils;
+import android.os.Build;
+
+import com.android.server.pm.parsing.pkg.AndroidPackage;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class CompatibilityModeTest {
+
+ private boolean mCompatibilityModeEnabled;;
+ private AndroidPackage mMockAndroidPackage;
+ private PackageUserState mMockUserState;
+
+ @Before
+ public void setUp() {
+ mCompatibilityModeEnabled = PackageParser.sCompatibilityModeEnabled;
+ mMockAndroidPackage = mock(AndroidPackage.class);
+ mMockUserState = mock(PackageUserState.class);
+ mMockUserState.installed = true;
+ when(mMockUserState.isAvailable(anyInt())).thenReturn(true);
+ when(mMockUserState.getAllOverlayPaths()).thenReturn(null);
+ }
+
+ @After
+ public void tearDown() {
+ setGlobalCompatibilityMode(mCompatibilityModeEnabled);
+ }
+
+ // The following tests ensure that apps with target SDK of Cupcake always use compat mode.
+
+ @Test
+ public void testGlobalCompatModeEnabled_oldApp_supportAllScreens_usesCompatMode() {
+ setGlobalCompatibilityMode(true);
+ final int flags = (FLAG_SUPPORTS_LARGE_SCREENS | FLAG_SUPPORTS_NORMAL_SCREENS
+ | FLAG_SUPPORTS_SMALL_SCREENS | FLAG_RESIZEABLE_FOR_SCREENS
+ | FLAG_SUPPORTS_SCREEN_DENSITIES | FLAG_SUPPORTS_XLARGE_SCREENS);
+ final ApplicationInfo info =
+ generateMockApplicationInfo(Build.VERSION_CODES.CUPCAKE, flags);
+ assertThat(info.usesCompatibilityMode(), is(true));
+ }
+
+ @Test
+ public void testGlobalCompatModeEnabled_oldApp_supportSomeScreens_usesCompatMode() {
+ setGlobalCompatibilityMode(true);
+ final int flags = (FLAG_SUPPORTS_LARGE_SCREENS
+ | FLAG_SUPPORTS_SMALL_SCREENS | FLAG_RESIZEABLE_FOR_SCREENS
+ | FLAG_SUPPORTS_SCREEN_DENSITIES | FLAG_SUPPORTS_XLARGE_SCREENS);
+ final ApplicationInfo info =
+ generateMockApplicationInfo(Build.VERSION_CODES.CUPCAKE, flags);
+ assertThat(info.usesCompatibilityMode(), is(true));
+ }
+
+ @Test
+ public void testGlobalCompatModeEnabled_oldApp_supportOnlyOneScreen_usesCompatMode() {
+ setGlobalCompatibilityMode(true);
+ final int flags = FLAG_SUPPORTS_NORMAL_SCREENS;
+ final ApplicationInfo info =
+ generateMockApplicationInfo(Build.VERSION_CODES.CUPCAKE, flags);
+ assertThat(info.usesCompatibilityMode(), is(true));
+ }
+
+ @Test
+ public void testGlobalCompatModeEnabled_oldApp_DoesntSupportAllScreens_usesCompatMode() {
+ setGlobalCompatibilityMode(true);
+ final ApplicationInfo info =
+ generateMockApplicationInfo(Build.VERSION_CODES.CUPCAKE, 0 /*flags*/);
+ assertThat(info.usesCompatibilityMode(), is(true));
+ }
+
+ @Test
+ public void testGlobalCompatModeDisabled_oldApp_supportAllScreens_usesCompatMode() {
+ setGlobalCompatibilityMode(false);
+ final int flags = (FLAG_SUPPORTS_LARGE_SCREENS | FLAG_SUPPORTS_NORMAL_SCREENS
+ | FLAG_SUPPORTS_SMALL_SCREENS | FLAG_RESIZEABLE_FOR_SCREENS
+ | FLAG_SUPPORTS_SCREEN_DENSITIES | FLAG_SUPPORTS_XLARGE_SCREENS);
+ final ApplicationInfo info =
+ generateMockApplicationInfo(Build.VERSION_CODES.CUPCAKE, flags);
+ assertThat(info.usesCompatibilityMode(), is(true));
+ }
+
+ @Test
+ public void testGlobalCompatModeDisabled_oldApp_supportSomeScreens_usesCompatMode() {
+ setGlobalCompatibilityMode(false);
+ final int flags = (FLAG_SUPPORTS_LARGE_SCREENS
+ | FLAG_SUPPORTS_SMALL_SCREENS | FLAG_RESIZEABLE_FOR_SCREENS
+ | FLAG_SUPPORTS_SCREEN_DENSITIES | FLAG_SUPPORTS_XLARGE_SCREENS);
+ final ApplicationInfo info =
+ generateMockApplicationInfo(Build.VERSION_CODES.CUPCAKE, flags);
+ assertThat(info.usesCompatibilityMode(), is(true));
+ }
+
+ @Test
+ public void testGlobalCompatModeDisabled_oldApp_supportOnlyOneScreen_usesCompatMode() {
+ setGlobalCompatibilityMode(false);
+ final int flags = FLAG_SUPPORTS_NORMAL_SCREENS;
+ final ApplicationInfo info =
+ generateMockApplicationInfo(Build.VERSION_CODES.CUPCAKE, flags);
+ assertThat(info.usesCompatibilityMode(), is(true));
+ }
+
+ @Test
+ public void testGlobalCompatModeDisabled_oldApp_doesntSupportAllScreens_usesCompatMode() {
+ setGlobalCompatibilityMode(false);
+ final ApplicationInfo info =
+ generateMockApplicationInfo(Build.VERSION_CODES.CUPCAKE, 0 /*flags*/);
+ assertThat(info.usesCompatibilityMode(), is(true));
+ }
+
+ // The following tests ensure that apps with newer target SDK use compat mode as expected.
+
+ @Test
+ public void testGlobalCompatModeEnabled_newApp_supportAllScreens_doesntUseCompatMode() {
+ setGlobalCompatibilityMode(true);
+ final int flags = (FLAG_SUPPORTS_LARGE_SCREENS | FLAG_SUPPORTS_NORMAL_SCREENS
+ | FLAG_SUPPORTS_SMALL_SCREENS | FLAG_RESIZEABLE_FOR_SCREENS
+ | FLAG_SUPPORTS_SCREEN_DENSITIES | FLAG_SUPPORTS_XLARGE_SCREENS);
+ final ApplicationInfo info = generateMockApplicationInfo(Build.VERSION_CODES.DONUT, flags);
+ assertThat(info.usesCompatibilityMode(), is(false));
+ }
+
+ @Test
+ public void testGlobalCompatModeEnabled_newApp_supportSomeScreens_doesntUseCompatMode() {
+ setGlobalCompatibilityMode(true);
+ final int flags = (FLAG_SUPPORTS_LARGE_SCREENS
+ | FLAG_SUPPORTS_SMALL_SCREENS | FLAG_RESIZEABLE_FOR_SCREENS
+ | FLAG_SUPPORTS_SCREEN_DENSITIES | FLAG_SUPPORTS_XLARGE_SCREENS);
+ final ApplicationInfo info = generateMockApplicationInfo(Build.VERSION_CODES.DONUT, flags);
+ assertThat(info.usesCompatibilityMode(), is(false));
+ }
+
+ @Test
+ public void testGlobalCompatModeEnabled_newApp_supportOnlyOneScreen_doesntUseCompatMode() {
+ setGlobalCompatibilityMode(true);
+ final int flags = FLAG_SUPPORTS_NORMAL_SCREENS;
+ final ApplicationInfo info = generateMockApplicationInfo(Build.VERSION_CODES.DONUT, flags);
+ assertThat(info.usesCompatibilityMode(), is(false));
+ }
+
+ @Test
+ public void testGlobalCompatModeEnabled_newApp_doesntSupportAllScreens_usesCompatMode() {
+ setGlobalCompatibilityMode(true);
+ final ApplicationInfo info =
+ generateMockApplicationInfo(Build.VERSION_CODES.DONUT, 0 /*flags*/);
+ assertThat(info.usesCompatibilityMode(), is(true));
+ }
+
+ @Test
+ public void testGlobalCompatModeDisabled_newApp_supportAllScreens_doesntUseCompatMode() {
+ setGlobalCompatibilityMode(false);
+ final int flags = (FLAG_SUPPORTS_LARGE_SCREENS | FLAG_SUPPORTS_NORMAL_SCREENS
+ | FLAG_SUPPORTS_SMALL_SCREENS | FLAG_RESIZEABLE_FOR_SCREENS
+ | FLAG_SUPPORTS_SCREEN_DENSITIES | FLAG_SUPPORTS_XLARGE_SCREENS);
+ final ApplicationInfo info = generateMockApplicationInfo(Build.VERSION_CODES.DONUT, flags);
+ assertThat(info.usesCompatibilityMode(), is(false));
+ }
+
+ @Test
+ public void testGlobalCompatModeDisabled_newApp_supportSomeScreens_doesntUseCompatMode() {
+ setGlobalCompatibilityMode(false);
+ final int flags = (FLAG_SUPPORTS_LARGE_SCREENS
+ | FLAG_SUPPORTS_SMALL_SCREENS | FLAG_RESIZEABLE_FOR_SCREENS
+ | FLAG_SUPPORTS_SCREEN_DENSITIES | FLAG_SUPPORTS_XLARGE_SCREENS);
+ final ApplicationInfo info = generateMockApplicationInfo(Build.VERSION_CODES.DONUT, flags);
+ assertThat(info.usesCompatibilityMode(), is(false));
+ }
+
+ @Test
+ public void testGlobalCompatModeDisabled_newApp_supportOnlyOneScreen_doesntUseCompatMode() {
+ setGlobalCompatibilityMode(false);
+ final int flags = FLAG_SUPPORTS_NORMAL_SCREENS;
+ final ApplicationInfo info = generateMockApplicationInfo(Build.VERSION_CODES.DONUT, flags);
+ assertThat(info.usesCompatibilityMode(), is(false));
+ }
+
+ @Test
+ public void testGlobalCompatModeDisabled_newApp_doesntSupportAllScreens_doesntUseCompatMode() {
+ setGlobalCompatibilityMode(false);
+ final ApplicationInfo info =
+ generateMockApplicationInfo(Build.VERSION_CODES.DONUT, 0 /*flags*/);
+ assertThat(info.usesCompatibilityMode(), is(false));
+ }
+
+ private ApplicationInfo generateMockApplicationInfo(int targetSdkVersion, int flags) {
+ final ApplicationInfo info = new ApplicationInfo();
+ info.targetSdkVersion = targetSdkVersion;
+ info.flags |= flags;
+ when(mMockAndroidPackage.toAppInfoWithoutState()).thenReturn(info);
+ return PackageInfoWithoutStateUtils.generateApplicationInfoUnchecked(mMockAndroidPackage,
+ 0 /*flags*/, mMockUserState, 0 /*userId*/, false /*assignUserFields*/);
+ }
+
+ private void setGlobalCompatibilityMode(boolean enabled) {
+ if (PackageParser.sCompatibilityModeEnabled == enabled) {
+ return;
+ }
+ PackageParser.setCompatibilityModeEnabled(enabled);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingTestBase.kt b/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingTestBase.kt
index 57436f8..581ff54 100644
--- a/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingTestBase.kt
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingTestBase.kt
@@ -509,7 +509,13 @@
.ignored("Checked separately in test")}
reqFeatures=${this.reqFeatures?.joinToString { it.dumpToString() }}
requestedPermissions=${this.requestedPermissions?.contentToString()}
- requestedPermissionsFlags=${this.requestedPermissionsFlags?.contentToString()}
+ requestedPermissionsFlags=${
+ this.requestedPermissionsFlags?.map {
+ // Newer flags are stripped
+ it and (PackageInfo.REQUESTED_PERMISSION_REQUIRED
+ or PackageInfo.REQUESTED_PERMISSION_GRANTED)
+ }?.joinToString()
+ }
requiredAccountType=${this.requiredAccountType}
requiredForAllUsers=${this.requiredForAllUsers}
restrictedAccountType=${this.restrictedAccountType}
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowOrientationListenerTest.java b/services/tests/servicestests/src/com/android/server/wm/WindowOrientationListenerTest.java
index 0e615a6..9ce3bf4 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowOrientationListenerTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowOrientationListenerTest.java
@@ -31,6 +31,7 @@
import android.os.CancellationSignal;
import android.os.Handler;
import android.rotationresolver.RotationResolverInternal;
+import android.service.rotationresolver.RotationResolverService;
import android.view.Surface;
import org.junit.Before;
@@ -42,37 +43,37 @@
* Tests for {@link com.android.server.wm.WindowOrientationListener}
*/
public class WindowOrientationListenerTest {
+ private static final int DEFAULT_SENSOR_ROTATION = Surface.ROTATION_90;
@Mock
private Context mMockContext;
@Mock
- private Handler mMockHandler;
- @Mock
private InputSensorInfo mMockInputSensorInfo;
@Mock
private SensorManager mMockSensorManager;
-
private TestableRotationResolver mFakeRotationResolverInternal;
- private com.android.server.wm.WindowOrientationListener mWindowOrientationListener;
+ private TestableWindowOrientationListener mWindowOrientationListener;
private int mFinalizedRotation;
private boolean mRotationResolverEnabled;
private SensorEvent mFakeSensorEvent;
private Sensor mFakeSensor;
+ private Handler mHandler;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mRotationResolverEnabled = true;
+ mHandler = Handler.getMain();
mFakeRotationResolverInternal = new TestableRotationResolver();
doReturn(mMockSensorManager).when(mMockContext).getSystemService(Context.SENSOR_SERVICE);
mWindowOrientationListener = new TestableWindowOrientationListener(mMockContext,
- mMockHandler);
+ mHandler);
mWindowOrientationListener.mRotationResolverService = mFakeRotationResolverInternal;
mFakeSensor = new Sensor(mMockInputSensorInfo);
mFakeSensorEvent = new SensorEvent(mFakeSensor, /* accuracy */ 1, /* timestamp */ 1L,
- new float[]{(float) Surface.ROTATION_90});
+ new float[]{(float) DEFAULT_SENSOR_ROTATION});
}
@Test
@@ -81,21 +82,49 @@
mWindowOrientationListener.mOrientationJudge.onSensorChanged(mFakeSensorEvent);
- assertThat(mFinalizedRotation).isEqualTo(Surface.ROTATION_90);
+ assertThat(mFinalizedRotation).isEqualTo(DEFAULT_SENSOR_ROTATION);
}
@Test
- public void testOnSensorChanged_normalCase() {
- mFakeRotationResolverInternal.mResult = Surface.ROTATION_180;
+ public void testOnSensorChanged_callbackNotTheLatest_IgnoreResult() {
+ mWindowOrientationListener.mOrientationJudge.onSensorChanged(mFakeSensorEvent);
+ final RotationResolverInternal.RotationResolverCallbackInternal callback1 =
+ mFakeRotationResolverInternal.getCallback();
mWindowOrientationListener.mOrientationJudge.onSensorChanged(mFakeSensorEvent);
+ final RotationResolverInternal.RotationResolverCallbackInternal callback2 =
+ mFakeRotationResolverInternal.getCallback();
+
+ callback1.onSuccess(Surface.ROTATION_180);
+ assertThat(mWindowOrientationListener.mIsOnProposedRotationChangedCalled).isFalse();
+
+ callback2.onSuccess(Surface.ROTATION_270);
+ assertThat(mWindowOrientationListener.mIsOnProposedRotationChangedCalled).isTrue();
+ assertThat(mFinalizedRotation).isEqualTo(Surface.ROTATION_270);
+ }
+
+ @Test
+ public void testOnSensorChanged_normalCase1() {
+ mWindowOrientationListener.mOrientationJudge.onSensorChanged(mFakeSensorEvent);
+
+ mFakeRotationResolverInternal.callbackWithSuccessResult(Surface.ROTATION_180);
assertThat(mFinalizedRotation).isEqualTo(Surface.ROTATION_180);
}
- final class TestableRotationResolver extends RotationResolverInternal {
+ @Test
+ public void testSensorChanged_normalCase2() {
+ mWindowOrientationListener.mOrientationJudge.onSensorChanged(mFakeSensorEvent);
+
+ mFakeRotationResolverInternal.callbackWithFailureResult(
+ RotationResolverService.ROTATION_RESULT_FAILURE_CANCELLED);
+
+ assertThat(mFinalizedRotation).isEqualTo(DEFAULT_SENSOR_ROTATION);
+ }
+
+ static final class TestableRotationResolver extends RotationResolverInternal {
@Surface.Rotation
- int mResult;
+ RotationResolverCallbackInternal mCallback;
@Override
public boolean isRotationResolverSupported() {
@@ -107,11 +136,28 @@
String packageName, @Surface.Rotation int proposedRotation,
@Surface.Rotation int currentRotation, @DurationMillisLong long timeoutMillis,
@NonNull CancellationSignal cancellationSignal) {
- callback.onSuccess(mResult);
+ mCallback = callback;
+ }
+
+ public RotationResolverCallbackInternal getCallback() {
+ return mCallback;
+ }
+
+ public void callbackWithSuccessResult(int result) {
+ if (mCallback != null) {
+ mCallback.onSuccess(result);
+ }
+ }
+
+ public void callbackWithFailureResult(int error) {
+ if (mCallback != null) {
+ mCallback.onFailure(error);
+ }
}
}
final class TestableWindowOrientationListener extends WindowOrientationListener {
+ boolean mIsOnProposedRotationChangedCalled = false;
TestableWindowOrientationListener(Context context, Handler handler) {
super(context, handler);
@@ -121,6 +167,7 @@
@Override
public void onProposedRotationChanged(int rotation) {
mFinalizedRotation = rotation;
+ mIsOnProposedRotationChangedCalled = true;
}
@Override
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java
index ab54526..50ebffc31 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java
@@ -197,7 +197,7 @@
si.packageName = "new";
si.name = "comp";
si.metaData = new Bundle();
- si.metaData.putString(NotificationListenerService.META_DATA_DEFAULT_FILTER_TYPES, "1,2");
+ si.metaData.putString(NotificationListenerService.META_DATA_DEFAULT_FILTER_TYPES, "1|2");
mListeners.ensureFilters(si, 0);
@@ -213,7 +213,7 @@
si.name = "comp";
si.metaData = new Bundle();
si.metaData.putString(NotificationListenerService.META_DATA_DEFAULT_FILTER_TYPES,
- "conversations,ALERTING");
+ "conversations|ALERTING");
mListeners.ensureFilters(si, 0);
@@ -243,7 +243,7 @@
si.packageName = "new";
si.name = "comp";
si.metaData = new Bundle();
- si.metaData.putString(NotificationListenerService.META_DATA_DISABLED_FILTER_TYPES, "1,2");
+ si.metaData.putString(NotificationListenerService.META_DATA_DISABLED_FILTER_TYPES, "1|2");
mListeners.ensureFilters(si, 0);
@@ -259,7 +259,7 @@
si.name = "comp";
si.metaData = new Bundle();
si.metaData.putString(NotificationListenerService.META_DATA_DISABLED_FILTER_TYPES,
- "1,alerting");
+ "1|alerting");
mListeners.ensureFilters(si, 0);
@@ -274,7 +274,7 @@
si.packageName = "new";
si.name = "comp";
si.metaData = new Bundle();
- si.metaData.putString(NotificationListenerService.META_DATA_DEFAULT_FILTER_TYPES, "1,2");
+ si.metaData.putString(NotificationListenerService.META_DATA_DEFAULT_FILTER_TYPES, "1|2");
si.metaData.putInt(NotificationListenerService.META_DATA_DISABLED_FILTER_TYPES, 1);
mListeners.ensureFilters(si, 0);
diff --git a/services/tests/wmtests/AndroidManifest.xml b/services/tests/wmtests/AndroidManifest.xml
index de4698d..985b2d5 100644
--- a/services/tests/wmtests/AndroidManifest.xml
+++ b/services/tests/wmtests/AndroidManifest.xml
@@ -41,6 +41,7 @@
<uses-permission android:name="android.permission.CAPTURE_VIDEO_OUTPUT" />
<uses-permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG" />
<uses-permission android:name="android.permission.LOG_COMPAT_CHANGE" />
+ <uses-permission android:name="android.permission.CAPTURE_BLACKOUT_CONTENT"/>
<!-- TODO: Remove largeHeap hack when memory leak is fixed (b/123984854) -->
<application android:debuggable="true"
@@ -75,6 +76,7 @@
<activity android:name="com.android.server.wm.ActivityOptionsTest$MainActivity"
android:turnScreenOn="true"
android:showWhenLocked="true" />
+ <activity android:name="com.android.server.wm.ScreenshotTests$ScreenshotActivity" />
</application>
<instrumentation
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index e09606e..6d4454b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -349,7 +349,9 @@
doReturn(imeSurfaceParent).when(mDisplayContent).computeImeParent();
spyOn(imeContainer);
- mDisplayContent.updateImeParent();
+ mDisplayContent.setImeInputTarget(startingWin);
+ mDisplayContent.onConfigurationChanged(new Configuration());
+ verify(mDisplayContent).updateImeParent();
// Force reassign the relative layer when the IME surface parent is changed.
verify(imeContainer).assignRelativeLayer(any(), eq(imeSurfaceParent), anyInt(), eq(true));
@@ -1275,6 +1277,7 @@
// Assume that the display rotation is changed so it is frozen in preparation for animation.
doReturn(true).when(rotationAnim).hasScreenshot();
mWm.mDisplayFrozen = true;
+ displayContent.getDisplayRotation().setRotation((displayContent.getRotation() + 1) % 4);
displayContent.setRotationAnimation(rotationAnim);
// The fade rotation animation also starts to hide some non-app windows.
assertNotNull(displayContent.getFadeRotationAnimationController());
@@ -1904,7 +1907,7 @@
mDisplayContent.setImeInputTarget(appWin2);
mDisplayContent.computeImeTarget(true);
assertEquals(appWin2, mDisplayContent.getImeTarget(IME_TARGET_LAYERING));
- assertTrue(mDisplayContent.isImeAttachedToApp());
+ assertTrue(mDisplayContent.shouldImeAttachedToApp());
verify(mDisplayContent, atLeast(1)).attachAndShowImeScreenshotOnTarget();
verify(mWm.mTaskSnapshotController).snapshotImeFromAttachedTask(appWin1.getTask());
diff --git a/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
index 1bddd7b..8981ab1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
@@ -239,6 +239,41 @@
}
@Test
+ public void testPrivateInterceptGlobalDragDropIgnoresNonLocalWindows() {
+ WindowState nonLocalWindow = createDropTargetWindow("App drag test window", 0);
+ WindowState globalInterceptWindow = createDropTargetWindow("Global drag test window", 0);
+ globalInterceptWindow.mAttrs.privateFlags |= PRIVATE_FLAG_INTERCEPT_GLOBAL_DRAG_AND_DROP;
+
+ // Necessary for now since DragState.sendDragStartedLocked() will recycle drag events
+ // immediately after dispatching, which is a problem when using mockito arguments captor
+ // because it returns and modifies the same drag event
+ TestIWindow localIWindow = (TestIWindow) mWindow.mClient;
+ final ArrayList<DragEvent> localWindowDragEvents = new ArrayList<>();
+ localIWindow.setDragEventJournal(localWindowDragEvents);
+ TestIWindow nonLocalIWindow = (TestIWindow) nonLocalWindow.mClient;
+ final ArrayList<DragEvent> nonLocalWindowDragEvents = new ArrayList<>();
+ nonLocalIWindow.setDragEventJournal(nonLocalWindowDragEvents);
+ TestIWindow globalInterceptIWindow = (TestIWindow) globalInterceptWindow.mClient;
+ final ArrayList<DragEvent> globalInterceptWindowDragEvents = new ArrayList<>();
+ globalInterceptIWindow.setDragEventJournal(globalInterceptWindowDragEvents);
+
+ startDrag(View.DRAG_FLAG_GLOBAL | View.DRAG_FLAG_GLOBAL_URI_READ,
+ createClipDataForActivity(null, mock(UserHandle.class)), () -> {
+ // Verify the start-drag event is sent for the local and global intercept window
+ // but not the other window
+ assertTrue(nonLocalWindowDragEvents.isEmpty());
+ assertTrue(localWindowDragEvents.get(0).getAction()
+ == ACTION_DRAG_STARTED);
+ assertTrue(globalInterceptWindowDragEvents.get(0).getAction()
+ == ACTION_DRAG_STARTED);
+
+ mTarget.reportDropWindow(globalInterceptWindow.mInputChannelToken, 0, 0);
+ mTarget.handleMotionEvent(false, 0, 0);
+ mToken = globalInterceptWindow.mClient.asBinder();
+ });
+ }
+
+ @Test
public void testValidateAppActivityArguments() {
final Session session = new Session(mWm, new IWindowSessionCallback.Stub() {
@Override
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
index 95b5afc..5af68021 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
@@ -1143,6 +1143,48 @@
assertNull(lastSnapshotData.bufferSize);
}
+ @Test
+ public void testCreateRecentTaskInfo_detachedTask() {
+ final Task task = createTaskBuilder(".Task").setCreateActivity(true).build();
+ final TaskDisplayArea tda = task.getDisplayArea();
+
+ assertTrue(task.isAttached());
+ assertTrue(task.supportsMultiWindow());
+
+ RecentTaskInfo info = mRecentTasks.createRecentTaskInfo(task, true);
+
+ assertTrue(info.supportsMultiWindow);
+ assertTrue(info.supportsSplitScreenMultiWindow);
+
+ // The task can be put in split screen even if it is not attached now.
+ task.removeImmediately();
+
+ info = mRecentTasks.createRecentTaskInfo(task, true);
+
+ assertTrue(info.supportsMultiWindow);
+ assertTrue(info.supportsSplitScreenMultiWindow);
+
+ // Test non-resizable.
+ // The non-resizable task cannot be put in split screen because of the config.
+ doReturn(false).when(tda).supportsNonResizableMultiWindow();
+ doReturn(false).when(task).isResizeable();
+
+ info = mRecentTasks.createRecentTaskInfo(task, true);
+
+ assertFalse(info.supportsMultiWindow);
+ assertFalse(info.supportsSplitScreenMultiWindow);
+
+ // Even if it is not attached, the non-resizable task can be put in split screen as long as
+ // the device supports it.
+ doReturn(true).when(tda).supportsNonResizableMultiWindow();
+
+ info = mRecentTasks.createRecentTaskInfo(task, true);
+
+ assertTrue(info.supportsMultiWindow);
+ assertTrue(info.supportsSplitScreenMultiWindow);
+
+ }
+
private TaskSnapshot createSnapshot(Point taskSize, Point bufferSize) {
HardwareBuffer buffer = null;
if (bufferSize != null) {
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
index 23d57b8..3082a5c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
@@ -516,20 +516,15 @@
final SurfaceControl.Transaction transaction = navToken.getPendingTransaction();
verify(mController.mStatusBar).setNavigationBarLumaSamplingEnabled(
- mDefaultDisplay.mDisplayId, false);
+ eq(mDefaultDisplay.mDisplayId), eq(false));
verify(transaction).reparent(navToken.getSurfaceControl(), activity.getSurfaceControl());
verify(transaction).setLayer(navToken.getSurfaceControl(), Integer.MAX_VALUE);
- final WindowContainer parent = navToken.getParent();
- final NavBarFadeAnimationController navBarFadeAnimationController =
- mDefaultDisplay.getDisplayPolicy().getNavBarFadeAnimationController();
-
mController.cleanupAnimation(REORDER_MOVE_TO_TOP);
+ verify(mController).restoreNavigationBarFromApp(eq(true));
verify(mController.mStatusBar).setNavigationBarLumaSamplingEnabled(
- mDefaultDisplay.mDisplayId, true);
+ eq(mDefaultDisplay.mDisplayId), eq(true));
verify(transaction).setLayer(navToken.getSurfaceControl(), 0);
- verify(transaction).reparent(navToken.getSurfaceControl(), parent.getSurfaceControl());
- verify(navBarFadeAnimationController).fadeWindowToken(true);
}
@Test
@@ -543,20 +538,18 @@
final SurfaceControl.Transaction transaction = navToken.getPendingTransaction();
verify(mController.mStatusBar).setNavigationBarLumaSamplingEnabled(
- mDefaultDisplay.mDisplayId, false);
+ eq(mDefaultDisplay.mDisplayId), eq(false));
verify(transaction).reparent(navToken.getSurfaceControl(), activity.getSurfaceControl());
verify(transaction).setLayer(navToken.getSurfaceControl(), Integer.MAX_VALUE);
final WindowContainer parent = navToken.getParent();
- final NavBarFadeAnimationController navBarFadeAnimationController =
- mDefaultDisplay.getDisplayPolicy().getNavBarFadeAnimationController();
mController.cleanupAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION);
+ verify(mController).restoreNavigationBarFromApp(eq(false));
verify(mController.mStatusBar).setNavigationBarLumaSamplingEnabled(
- mDefaultDisplay.mDisplayId, true);
+ eq(mDefaultDisplay.mDisplayId), eq(true));
verify(transaction).setLayer(navToken.getSurfaceControl(), 0);
verify(transaction).reparent(navToken.getSurfaceControl(), parent.getSurfaceControl());
- verify(navBarFadeAnimationController, never()).fadeWindowToken(anyBoolean());
}
@Test
@@ -571,39 +564,6 @@
}
@Test
- public void testFadeRotationAfterAttachAndBeforeRestore_notRestoreNavImmediately() {
- setupForShouldAttachNavBarDuringTransition();
- final ActivityRecord activity = createActivityRecord(mDefaultDisplay);
- final ActivityRecord homeActivity = createHomeActivity();
- initializeRecentsAnimationController(mController, homeActivity);
-
- final WindowToken navToken = mDefaultDisplay.getDisplayPolicy().getNavigationBar().mToken;
- final SurfaceControl.Transaction transaction = navToken.getPendingTransaction();
-
- verify(mController.mStatusBar).setNavigationBarLumaSamplingEnabled(
- mDefaultDisplay.mDisplayId, false);
- verify(transaction).reparent(navToken.getSurfaceControl(), activity.getSurfaceControl());
- verify(transaction).setLayer(navToken.getSurfaceControl(), Integer.MAX_VALUE);
-
- final WindowContainer parent = navToken.getParent();
- final NavBarFadeAnimationController navBarFadeAnimationController =
- mDefaultDisplay.getDisplayPolicy().getNavBarFadeAnimationController();
-
- FadeRotationAnimationController mockController =
- mock(FadeRotationAnimationController.class);
- doReturn(mockController).when(mDefaultDisplay).getFadeRotationAnimationController();
-
- mController.cleanupAnimation(REORDER_MOVE_TO_TOP);
- verify(mController.mStatusBar).setNavigationBarLumaSamplingEnabled(
- mDefaultDisplay.mDisplayId, true);
- verify(transaction).setLayer(navToken.getSurfaceControl(), 0);
- verify(mockController).setOnShowRunnable(any());
- verify(transaction, times(0)).reparent(navToken.getSurfaceControl(),
- parent.getSurfaceControl());
- verify(navBarFadeAnimationController, times(0)).fadeWindowToken(true);
- }
-
- @Test
public void testAttachNavBarInSplitScreenMode() {
setupForShouldAttachNavBarDuringTransition();
final ActivityRecord primary = createActivityRecordWithParentTask(mDefaultDisplay,
@@ -619,20 +579,18 @@
final SurfaceControl.Transaction transaction = navToken.getPendingTransaction();
verify(mController.mStatusBar).setNavigationBarLumaSamplingEnabled(
- mDefaultDisplay.mDisplayId, false);
+ eq(mDefaultDisplay.mDisplayId), eq(false));
verify(navWindow).setSurfaceTranslationY(-secondary.getBounds().top);
verify(transaction).reparent(navToken.getSurfaceControl(), secondary.getSurfaceControl());
reset(navWindow);
mController.cleanupAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION);
final WindowContainer parent = navToken.getParent();
- final NavBarFadeAnimationController navBarFadeAnimationController =
- mDefaultDisplay.getDisplayPolicy().getNavBarFadeAnimationController();
verify(mController.mStatusBar).setNavigationBarLumaSamplingEnabled(
- mDefaultDisplay.mDisplayId, true);
+ eq(mDefaultDisplay.mDisplayId), eq(true));
verify(navWindow).setSurfaceTranslationY(0);
verify(transaction).reparent(navToken.getSurfaceControl(), parent.getSurfaceControl());
- verify(navBarFadeAnimationController, never()).fadeWindowToken(anyBoolean());
+ verify(mController).restoreNavigationBarFromApp(eq(false));
}
@Test
@@ -696,12 +654,8 @@
mDefaultDisplay.getDisplayPolicy().addWindowLw(navBar, navBar.mAttrs);
mWm.setRecentsAnimationController(mController);
doReturn(navBar).when(mController).getNavigationBarWindow();
- final NavBarFadeAnimationController mockNavBarFadeAnimationController =
- mock(NavBarFadeAnimationController.class);
final DisplayPolicy displayPolicy = spy(mDefaultDisplay.getDisplayPolicy());
doReturn(displayPolicy).when(mDefaultDisplay).getDisplayPolicy();
- doReturn(mockNavBarFadeAnimationController).when(displayPolicy)
- .getNavBarFadeAnimationController();
}
private static void initializeRecentsAnimationController(RecentsAnimationController controller,
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
index 7614579..9267285 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
@@ -560,7 +560,7 @@
// Verify the target task should resume its activity.
verify(rootTask, times(1)).resumeTopActivityUncheckedLocked(
- eq(activity), eq(null /* targetOptions */));
+ eq(activity), eq(null /* targetOptions */), eq(false));
}
/**
diff --git a/services/tests/wmtests/src/com/android/server/wm/ScreenshotTests.java b/services/tests/wmtests/src/com/android/server/wm/ScreenshotTests.java
new file mode 100644
index 0000000..f542e29
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/wm/ScreenshotTests.java
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ColorSpace;
+import android.graphics.GraphicBuffer;
+import android.graphics.PixelFormat;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.platform.test.annotations.Presubmit;
+import android.view.PointerIcon;
+import android.view.SurfaceControl;
+import android.view.WindowManager;
+
+import androidx.annotation.Nullable;
+import androidx.test.filters.SmallTest;
+import androidx.test.rule.ActivityTestRule;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Build/Install/Run:
+ * atest WmTests:ScreenshotTests
+ */
+@SmallTest
+@Presubmit
+public class ScreenshotTests {
+ private static final int BUFFER_WIDTH = 100;
+ private static final int BUFFER_HEIGHT = 100;
+
+ private final Instrumentation mInstrumentation = getInstrumentation();
+
+ @Rule
+ public ActivityTestRule<ScreenshotActivity> mActivityRule =
+ new ActivityTestRule<>(ScreenshotActivity.class);
+
+ private ScreenshotActivity mActivity;
+
+ @Before
+ public void setup() {
+ mActivity = mActivityRule.getActivity();
+ mInstrumentation.waitForIdleSync();
+ }
+
+ @Test
+ public void testScreenshotSecureLayers() {
+ SurfaceControl secureSC = new SurfaceControl.Builder()
+ .setName("SecureChildSurfaceControl")
+ .setBLASTLayer()
+ .setCallsite("makeSecureSurfaceControl")
+ .setSecure(true)
+ .build();
+
+ SurfaceControl.Transaction t = mActivity.addChildSc(secureSC);
+ mInstrumentation.waitForIdleSync();
+
+ GraphicBuffer buffer = GraphicBuffer.create(BUFFER_WIDTH, BUFFER_HEIGHT,
+ PixelFormat.RGBA_8888,
+ GraphicBuffer.USAGE_HW_TEXTURE | GraphicBuffer.USAGE_HW_COMPOSER
+ | GraphicBuffer.USAGE_SW_WRITE_RARELY);
+
+ Canvas canvas = buffer.lockCanvas();
+ canvas.drawColor(Color.RED);
+ buffer.unlockCanvasAndPost(canvas);
+
+ t.show(secureSC)
+ .setBuffer(secureSC, buffer)
+ .setColorSpace(secureSC, ColorSpace.get(ColorSpace.Named.SRGB))
+ .apply(true);
+
+ SurfaceControl.LayerCaptureArgs args = new SurfaceControl.LayerCaptureArgs.Builder(secureSC)
+ .setCaptureSecureLayers(true)
+ .setChildrenOnly(false)
+ .build();
+ SurfaceControl.ScreenshotHardwareBuffer hardwareBuffer = SurfaceControl.captureLayers(args);
+ assertNotNull(hardwareBuffer);
+
+ Bitmap screenshot = hardwareBuffer.asBitmap();
+ assertNotNull(screenshot);
+
+ Bitmap swBitmap = screenshot.copy(Bitmap.Config.ARGB_8888, false);
+ screenshot.recycle();
+
+ int numMatchingPixels = PixelChecker.getNumMatchingPixels(swBitmap,
+ new PixelColor(PixelColor.RED));
+ long sizeOfBitmap = swBitmap.getWidth() * swBitmap.getHeight();
+ boolean success = numMatchingPixels == sizeOfBitmap;
+ swBitmap.recycle();
+
+ assertTrue(success);
+ }
+
+ public static class ScreenshotActivity extends Activity {
+ private static final long WAIT_TIMEOUT_S = 5;
+ private final Handler mHandler = new Handler(Looper.getMainLooper());
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ getWindow().getDecorView().setPointerIcon(
+ PointerIcon.getSystemIcon(this, PointerIcon.TYPE_NULL));
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+ }
+
+ SurfaceControl.Transaction addChildSc(SurfaceControl surfaceControl) {
+ SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+ CountDownLatch countDownLatch = new CountDownLatch(1);
+ mHandler.post(() -> {
+ t.merge(getWindow().getRootSurfaceControl().buildReparentTransaction(
+ surfaceControl));
+ countDownLatch.countDown();
+ });
+
+ try {
+ countDownLatch.await(WAIT_TIMEOUT_S, TimeUnit.SECONDS);
+ } catch (InterruptedException e) {
+ }
+ return t;
+ }
+ }
+
+ public abstract static class PixelChecker {
+ static int getNumMatchingPixels(Bitmap bitmap, PixelColor pixelColor) {
+ int numMatchingPixels = 0;
+ for (int x = 0; x < bitmap.getWidth(); x++) {
+ for (int y = 0; y < bitmap.getHeight(); y++) {
+ int color = bitmap.getPixel(x, y);
+ if (matchesColor(pixelColor, color)) {
+ numMatchingPixels++;
+ }
+ }
+ }
+ return numMatchingPixels;
+ }
+
+ static boolean matchesColor(PixelColor expectedColor, int color) {
+ final float red = Color.red(color);
+ final float green = Color.green(color);
+ final float blue = Color.blue(color);
+ final float alpha = Color.alpha(color);
+
+ return alpha <= expectedColor.mMaxAlpha
+ && alpha >= expectedColor.mMinAlpha
+ && red <= expectedColor.mMaxRed
+ && red >= expectedColor.mMinRed
+ && green <= expectedColor.mMaxGreen
+ && green >= expectedColor.mMinGreen
+ && blue <= expectedColor.mMaxBlue
+ && blue >= expectedColor.mMinBlue;
+ }
+ }
+
+ public static class PixelColor {
+ public static final int BLACK = 0xFF000000;
+ public static final int RED = 0xFF0000FF;
+ public static final int GREEN = 0xFF00FF00;
+ public static final int BLUE = 0xFFFF0000;
+ public static final int YELLOW = 0xFF00FFFF;
+ public static final int MAGENTA = 0xFFFF00FF;
+ public static final int WHITE = 0xFFFFFFFF;
+
+ public static final int TRANSPARENT_RED = 0x7F0000FF;
+ public static final int TRANSPARENT_BLUE = 0x7FFF0000;
+ public static final int TRANSPARENT = 0x00000000;
+
+ // Default to black
+ public short mMinAlpha;
+ public short mMaxAlpha;
+ public short mMinRed;
+ public short mMaxRed;
+ public short mMinBlue;
+ public short mMaxBlue;
+ public short mMinGreen;
+ public short mMaxGreen;
+
+ public PixelColor(int color) {
+ short alpha = (short) ((color >> 24) & 0xFF);
+ short blue = (short) ((color >> 16) & 0xFF);
+ short green = (short) ((color >> 8) & 0xFF);
+ short red = (short) (color & 0xFF);
+
+ mMinAlpha = (short) getMinValue(alpha);
+ mMaxAlpha = (short) getMaxValue(alpha);
+ mMinRed = (short) getMinValue(red);
+ mMaxRed = (short) getMaxValue(red);
+ mMinBlue = (short) getMinValue(blue);
+ mMaxBlue = (short) getMaxValue(blue);
+ mMinGreen = (short) getMinValue(green);
+ mMaxGreen = (short) getMaxValue(green);
+ }
+
+ public PixelColor() {
+ this(BLACK);
+ }
+
+ private int getMinValue(short color) {
+ return Math.max(color - 4, 0);
+ }
+
+ private int getMaxValue(short color) {
+ return Math.min(color + 4, 0xFF);
+ }
+ }
+}
diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
index 0925e12..7224a0e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -316,14 +316,14 @@
mActivity.mDisplayContent.setImeLayeringTarget(addWindowToActivity(mActivity));
// Make sure IME cannot attach to the app, otherwise IME window will also be shifted.
- assertFalse(mActivity.mDisplayContent.isImeAttachedToApp());
+ assertFalse(mActivity.mDisplayContent.shouldImeAttachedToApp());
// Recompute the natural configuration without resolving size compat configuration.
mActivity.clearSizeCompatMode();
mActivity.onConfigurationChanged(mTask.getConfiguration());
// It should keep non-attachable because the resolved bounds will be computed according to
// the aspect ratio that won't match its parent bounds.
- assertFalse(mActivity.mDisplayContent.isImeAttachedToApp());
+ assertFalse(mActivity.mDisplayContent.shouldImeAttachedToApp());
// Activity max bounds should be sandboxed since it is letterboxed.
assertActivityMaxBoundsSandboxed();
}
@@ -358,7 +358,7 @@
// Because the aspect ratio of display doesn't exceed the max aspect ratio of activity.
// The activity should still fill its parent container and IME can attach to the activity.
assertTrue(mActivity.matchParentBounds());
- assertTrue(mActivity.mDisplayContent.isImeAttachedToApp());
+ assertTrue(mActivity.mDisplayContent.shouldImeAttachedToApp());
final Rect letterboxInnerBounds = new Rect();
mActivity.getLetterboxInnerBounds(letterboxInnerBounds);
@@ -521,6 +521,7 @@
mActivity.setState(STOPPED, "testSizeCompatMode");
mActivity.mVisibleRequested = false;
+ mActivity.visibleIgnoringKeyguard = false;
mActivity.app.setReportedProcState(ActivityManager.PROCESS_STATE_CACHED_ACTIVITY);
// Simulate the display changes orientation.
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java
index 81712c6..e9e2013 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java
@@ -193,7 +193,7 @@
Task task = mAppWindow.mActivityRecord.getTask();
spyOn(task);
spyOn(mDisplayContent);
- when(task.getDisplayContent().isImeAttachedToApp()).thenReturn(false);
+ when(task.getDisplayContent().shouldImeAttachedToApp()).thenReturn(false);
// Intentionally set the SurfaceControl of input method window as null.
mDisplayContent.mInputMethodWindow.setSurfaceControl(null);
// Verify no NPE happens when calling createTaskSnapshot.
@@ -213,7 +213,7 @@
spyOn(task);
spyOn(mDisplayContent);
spyOn(mDisplayContent.mInputMethodWindow);
- when(task.getDisplayContent().isImeAttachedToApp()).thenReturn(true);
+ when(task.getDisplayContent().shouldImeAttachedToApp()).thenReturn(true);
// Intentionally set the IME window is in drawn state.
doReturn(true).when(mDisplayContent.mInputMethodWindow).isDrawn();
// Verify no NPE happens when calling createTaskSnapshot.
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
index 9226c0b..d93ebb3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
@@ -289,6 +289,9 @@
@Test
public void testResolveNonResizableTaskWindowingMode() {
+ // Test with no support non-resizable in multi window regardless the screen size.
+ mAtm.mSupportsNonResizableMultiWindow = -1;
+
final Task task = createTask(mDisplayContent);
Configuration parentConfig = task.getParent().getConfiguration();
parentConfig.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index 8d067be..152a575 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -20,6 +20,8 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+import static android.view.InsetsState.ITYPE_IME;
+import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
import static android.view.Surface.ROTATION_0;
import static android.view.Surface.ROTATION_270;
@@ -49,6 +51,7 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.server.wm.DisplayContent.IME_TARGET_CONTROL;
+import static com.android.server.wm.DisplayContent.IME_TARGET_LAYERING;
import static com.android.server.wm.WindowContainer.SYNC_STATE_WAITING_FOR_DRAW;
import static com.google.common.truth.Truth.assertThat;
@@ -57,6 +60,7 @@
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
@@ -78,6 +82,7 @@
import android.platform.test.annotations.Presubmit;
import android.view.Gravity;
import android.view.InputWindowHandle;
+import android.view.InsetsSource;
import android.view.InsetsState;
import android.view.SurfaceControl;
import android.view.WindowManager;
@@ -880,6 +885,22 @@
verify(app).notifyInsetsChanged();
}
+ @UseTestDisplay(addWindows = { W_INPUT_METHOD, W_ACTIVITY })
+ @Test
+ public void testImeAlwaysReceivesVisibleNavigationBarInsets() {
+ final InsetsSource navSource = new InsetsSource(ITYPE_NAVIGATION_BAR);
+ mImeWindow.mAboveInsetsState.addSource(navSource);
+ mAppWindow.mAboveInsetsState.addSource(navSource);
+
+ navSource.setVisible(false);
+ assertTrue(mImeWindow.getInsetsState().getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR));
+ assertFalse(mAppWindow.getInsetsState().getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR));
+
+ navSource.setVisible(true);
+ assertTrue(mImeWindow.getInsetsState().getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR));
+ assertTrue(mAppWindow.getInsetsState().getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR));
+ }
+
@UseTestDisplay(addWindows = { W_ACTIVITY })
@Test
public void testUpdateImeControlTargetWhenLeavingMultiWindow() {
@@ -905,4 +926,34 @@
verify(app.getDisplayContent()).updateImeControlTarget();
assertEquals(mAppWindow, mDisplayContent.getImeTarget(IME_TARGET_CONTROL).getWindow());
}
+
+ @UseTestDisplay(addWindows = { W_ACTIVITY, W_INPUT_METHOD, W_NOTIFICATION_SHADE })
+ @Test
+ public void testNotificationShadeHasImeInsetsWhenSplitscreenActivated() {
+ WindowState app = createWindow(null, TYPE_BASE_APPLICATION,
+ mAppWindow.mToken, "app");
+
+ // Simulate entering multi-window mode and verify if the split-screen is activated.
+ app.mActivityRecord.getRootTask().setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
+ assertEquals(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, app.getWindowingMode());
+ assertTrue(mDisplayContent.getDefaultTaskDisplayArea().isSplitScreenModeActivated());
+
+ // Simulate notificationShade is shown and being IME layering target.
+ mNotificationShadeWindow.setHasSurface(true);
+ mNotificationShadeWindow.mAttrs.flags &= ~FLAG_NOT_FOCUSABLE;
+ assertTrue(mNotificationShadeWindow.canBeImeTarget());
+ mDisplayContent.getInsetsStateController().getSourceProvider(ITYPE_IME).setWindow(
+ mImeWindow, null, null);
+
+ mDisplayContent.computeImeTarget(true);
+ assertEquals(mNotificationShadeWindow, mDisplayContent.getImeTarget(IME_TARGET_LAYERING));
+ mDisplayContent.getInsetsStateController().getRawInsetsState()
+ .setSourceVisible(ITYPE_IME, true);
+
+ // Verify notificationShade can still get IME insets even the split-screen is activated.
+ InsetsState state = mDisplayContent.getInsetsStateController().getInsetsForWindow(
+ mNotificationShadeWindow);
+ assertNotNull(state.peekSource(ITYPE_IME));
+ assertTrue(state.getSource(ITYPE_IME).isVisible());
+ }
}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
index 5df3d9c..aec0643 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
@@ -164,6 +164,11 @@
KEY_INITIALIZATION_STATUS,
INITIALIZATION_STATUS_UNKNOWN)
: INITIALIZATION_STATUS_UNKNOWN;
+ // Add the protection to avoid unexpected status
+ if (status > HotwordDetectionService.getMaxCustomInitializationStatus()
+ && status != INITIALIZATION_STATUS_UNKNOWN) {
+ status = INITIALIZATION_STATUS_UNKNOWN;
+ }
callback.onStatusReported(status);
} catch (RemoteException e) {
Slog.w(TAG, "Failed to report initialization status: " + e);
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 92cfe49..f3d80b1 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -234,6 +234,23 @@
VoiceInteractionManagerService.this.mServiceStub.stopLocalVoiceInteraction(
callingActivity);
}
+
+ @Override
+ public boolean hasActiveSession(String packageName) {
+ VoiceInteractionManagerServiceImpl impl =
+ VoiceInteractionManagerService.this.mServiceStub.mImpl;
+ if (impl == null) {
+ return false;
+ }
+
+ VoiceInteractionSessionConnection session =
+ impl.mActiveSession;
+ if (session == null) {
+ return false;
+ }
+
+ return TextUtils.equals(packageName, session.mSessionComponentName.getPackageName());
+ }
}
// implementation entry point and binder service
diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java
index 579b33e..e332d3f 100644
--- a/telecomm/java/android/telecom/PhoneAccount.java
+++ b/telecomm/java/android/telecom/PhoneAccount.java
@@ -27,6 +27,7 @@
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
+import android.telephony.CarrierConfigManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
@@ -283,10 +284,13 @@
* number relies on presence. Should only be set if the {@code PhoneAccount} also has
* {@link #CAPABILITY_VIDEO_CALLING}.
* <p>
- * When set, the {@link ConnectionService} is responsible for toggling the
+ * Note: As of Android 12, using the
* {@link android.provider.ContactsContract.Data#CARRIER_PRESENCE_VT_CAPABLE} bit on the
* {@link android.provider.ContactsContract.Data#CARRIER_PRESENCE} column to indicate whether
- * a contact's phone number supports video calling.
+ * a contact's phone number supports video calling has been deprecated and should only be used
+ * on devices where {@link CarrierConfigManager#KEY_USE_RCS_PRESENCE_BOOL} is set. On newer
+ * devices, applications must use {@link android.telephony.ims.RcsUceAdapter} instead to
+ * determine whether or not a contact's phone number supports carrier video calling.
* <p>
* See {@link #getCapabilities}
*/
diff --git a/telephony/common/com/google/android/mms/pdu/PduParser.java b/telephony/common/com/google/android/mms/pdu/PduParser.java
index 5340245..677fe2f 100755
--- a/telephony/common/com/google/android/mms/pdu/PduParser.java
+++ b/telephony/common/com/google/android/mms/pdu/PduParser.java
@@ -1550,6 +1550,11 @@
if (cur < TEXT_MIN) {
int length = parseValueLength(pduDataStream);
int startPos = pduDataStream.available();
+ if (length > startPos) {
+ Log.e(LOG_TAG, "parseContentType: Invalid length " + length
+ + " when available bytes are " + startPos);
+ return (PduContentTypes.contentTypes[0]).getBytes(); //"*/*"
+ }
pduDataStream.mark(1);
temp = pduDataStream.read();
assert(-1 != temp);
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 33a9a96..c527e66 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -38,6 +38,7 @@
import android.telephony.ims.ImsReasonInfo;
import android.telephony.ims.ImsRegistrationAttributes;
import android.telephony.ims.ImsSsData;
+import android.telephony.ims.RcsUceAdapter;
import android.telephony.ims.feature.MmTelFeature;
import android.telephony.ims.feature.RcsFeature;
@@ -4259,6 +4260,9 @@
* If this flag is disabled, the capabilities cache will not be refreshed internally at all
* and will only be updated if the cached capabilities are stale when an application
* requests them.
+ *
+ * @see RcsUceAdapter#isUceSettingEnabled() more information about this feature and how
+ * it is enabled by the user.
*/
public static final String KEY_RCS_BULK_CAPABILITY_EXCHANGE_BOOL =
KEY_PREFIX + "rcs_bulk_capability_exchange_bool";
@@ -5549,7 +5553,7 @@
sDefaults.putBoolean(KEY_STORE_SIM_PIN_FOR_UNATTENDED_REBOOT_BOOL, true);
sDefaults.putBoolean(KEY_HIDE_ENABLE_2G, false);
sDefaults.putStringArray(KEY_ALLOWED_INITIAL_ATTACH_APN_TYPES_STRING_ARRAY,
- new String[]{"ia", "default", "ims", "mms", "dun", "emergency"});
+ new String[]{"ia", "default", "mms", "dun"});
sDefaults.putBoolean(KEY_CARRIER_PROVISIONS_WIFI_MERGED_NETWORKS_BOOL, false);
sDefaults.putBoolean(KEY_USE_IP_FOR_CALLING_INDICATOR_BOOL, false);
sDefaults.putBoolean(KEY_DISPLAY_CALL_STRENGTH_INDICATOR_BOOL, true);
diff --git a/telephony/java/android/telephony/CellBroadcastService.java b/telephony/java/android/telephony/CellBroadcastService.java
index ac775b3..14de2f2 100644
--- a/telephony/java/android/telephony/CellBroadcastService.java
+++ b/telephony/java/android/telephony/CellBroadcastService.java
@@ -28,6 +28,11 @@
import android.os.RemoteCallback;
import android.telephony.cdma.CdmaSmsCbProgramData;
+import com.android.internal.util.FastPrintWriter;
+
+import java.io.FileDescriptor;
+import java.io.FileOutputStream;
+import java.io.PrintWriter;
import java.util.List;
import java.util.function.Consumer;
@@ -186,5 +191,16 @@
public @NonNull CharSequence getCellBroadcastAreaInfo(int slotIndex) {
return CellBroadcastService.this.getCellBroadcastAreaInfo(slotIndex);
}
+
+ @Override
+ protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
+ CellBroadcastService.this.dump(fd, fout, args);
+ }
+
+ @Override
+ public void dump(FileDescriptor fd, String[] args) {
+ PrintWriter pw = new FastPrintWriter(new FileOutputStream(fd));
+ CellBroadcastService.this.dump(fd, pw, args);
+ }
}
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 78da86c..64aa2994 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -8571,7 +8571,7 @@
* app has carrier privileges (see {@link #hasCarrierPrivileges}).
* <p>
* If {@link android.telephony.TelephonyManager#isRadioInterfaceCapabilitySupported}
- * ({@link TelephonyManager#CAPABILITY_ALLOWED_NETWORK_TYPES_USED}) returns true, then
+ * ({@link TelephonyManager#CAPABILITY_USES_ALLOWED_NETWORK_TYPES_BITMASK}) returns true, then
* setAllowedNetworkTypesBitmap is used on the radio interface. Otherwise,
* setPreferredNetworkTypesBitmap is used instead.
*
@@ -8609,7 +8609,7 @@
* app has carrier privileges (see {@link #hasCarrierPrivileges}).
* <p>
* If {@link android.telephony.TelephonyManager#isRadioInterfaceCapabilitySupported}
- * ({@link TelephonyManager#CAPABILITY_ALLOWED_NETWORK_TYPES_USED}) returns true, then
+ * ({@link TelephonyManager#CAPABILITY_USES_ALLOWED_NETWORK_TYPES_BITMASK}) returns true, then
* setAllowedNetworkTypesBitmap is used on the radio interface. Otherwise,
* setPreferredNetworkTypesBitmap is used instead.
*
@@ -8640,7 +8640,7 @@
* be set through {@link #setPreferredNetworkTypeBitmask}.
* <p>
* If {@link android.telephony.TelephonyManager#isRadioInterfaceCapabilitySupported}
- * ({@link TelephonyManager#CAPABILITY_ALLOWED_NETWORK_TYPES_USED}) returns true, then
+ * ({@link TelephonyManager#CAPABILITY_USES_ALLOWED_NETWORK_TYPES_BITMASK}) returns true, then
* setAllowedNetworkTypesBitmap is used on the radio interface. Otherwise,
* setPreferredNetworkTypesBitmap is used instead.
*
@@ -8653,7 +8653,7 @@
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
@RequiresFeature(
enforcement = "android.telephony.TelephonyManager#isRadioInterfaceCapabilitySupported",
- value = TelephonyManager.CAPABILITY_ALLOWED_NETWORK_TYPES_USED)
+ value = TelephonyManager.CAPABILITY_USES_ALLOWED_NETWORK_TYPES_BITMASK)
@SystemApi
public boolean setAllowedNetworkTypes(@NetworkTypeBitMask long allowedNetworkTypes) {
try {
@@ -8738,7 +8738,7 @@
* {@link TelephonyManager#setAllowedNetworkTypes}.
* <p>
* If {@link android.telephony.TelephonyManager#isRadioInterfaceCapabilitySupported}
- * ({@link TelephonyManager#CAPABILITY_ALLOWED_NETWORK_TYPES_USED}) returns true, then
+ * ({@link TelephonyManager#CAPABILITY_USES_ALLOWED_NETWORK_TYPES_BITMASK}) returns true, then
* setAllowedNetworkTypesBitmap is used on the radio interface. Otherwise,
* setPreferredNetworkTypesBitmap is used instead.
*
@@ -8752,7 +8752,7 @@
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
@RequiresFeature(
enforcement = "android.telephony.TelephonyManager#isRadioInterfaceCapabilitySupported",
- value = TelephonyManager.CAPABILITY_ALLOWED_NETWORK_TYPES_USED)
+ value = TelephonyManager.CAPABILITY_USES_ALLOWED_NETWORK_TYPES_BITMASK)
public void setAllowedNetworkTypesForReason(@AllowedNetworkTypesReason int reason,
@NetworkTypeBitMask long allowedNetworkTypes) {
if (!isValidAllowedNetworkTypesReason(reason)) {
@@ -8788,7 +8788,7 @@
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
@RequiresFeature(
enforcement = "android.telephony.TelephonyManager#isRadioInterfaceCapabilitySupported",
- value = TelephonyManager.CAPABILITY_ALLOWED_NETWORK_TYPES_USED)
+ value = TelephonyManager.CAPABILITY_USES_ALLOWED_NETWORK_TYPES_BITMASK)
@SystemApi
public @NetworkTypeBitMask long getAllowedNetworkTypesForReason(
@AllowedNetworkTypesReason int reason) {
@@ -14984,8 +14984,8 @@
* @hide
*/
@SystemApi
- public static final String CAPABILITY_ALLOWED_NETWORK_TYPES_USED =
- "CAPABILITY_ALLOWED_NETWORK_TYPES_USED";
+ public static final String CAPABILITY_USES_ALLOWED_NETWORK_TYPES_BITMASK =
+ "CAPABILITY_USES_ALLOWED_NETWORK_TYPES_BITMASK";
/**
* Indicates whether {@link #setNrDualConnectivityState()} and
@@ -15025,11 +15025,20 @@
"CAPABILITY_PHYSICAL_CHANNEL_CONFIG_1_6_SUPPORTED";
/**
+ * Indicates whether modem supports handling parsed SIM phonebook records through the RIL,
+ * both batched reads and individual writes.
+ *
+ * @hide
+ */
+ public static final String CAPABILITY_SIM_PHONEBOOK_IN_MODEM =
+ "CAPABILITY_SIM_PHONEBOOK_IN_MODEM";
+
+ /**
* A list of the radio interface capability values with public valid constants.
*
* Here is a related list for the systemapi-only valid constants:
* CAPABILITY_SECONDARY_LINK_BANDWIDTH_VISIBLE
- * CAPABILITY_ALLOWED_NETWORK_TYPES_USED
+ * CAPABILITY_USES_ALLOWED_NETWORK_TYPES_BITMASK
* CAPABILITY_NR_DUAL_CONNECTIVITY_CONFIGURATION_AVAILABLE
* CAPABILITY_THERMAL_MITIGATION_DATA_THROTTLING
*
@@ -15039,6 +15048,7 @@
@Retention(RetentionPolicy.SOURCE)
@StringDef(prefix = "CAPABILITY_", value = {
CAPABILITY_SLICING_CONFIG_SUPPORTED,
+ CAPABILITY_SIM_PHONEBOOK_IN_MODEM,
})
public @interface RadioInterfaceCapability {}
diff --git a/telephony/java/android/telephony/ims/ImsRcsManager.java b/telephony/java/android/telephony/ims/ImsRcsManager.java
index 814ce18..3700026 100644
--- a/telephony/java/android/telephony/ims/ImsRcsManager.java
+++ b/telephony/java/android/telephony/ims/ImsRcsManager.java
@@ -56,7 +56,9 @@
/**
* Activity Action: Show the opt-in dialog for enabling or disabling RCS contact discovery
- * using User Capability Exchange (UCE).
+ * using User Capability Exchange (UCE), which enables a service that periodically shares the
+ * phone numbers of all of the contacts in the user's address book with the carrier to refresh
+ * the RCS capabilities associated with those contacts as the local cache becomes stale.
* <p>
* An application that depends on RCS contact discovery being enabled must send this intent
* using {@link Context#startActivity(Intent)} to ask the user to opt-in for contacts upload for
diff --git a/telephony/java/android/telephony/ims/RcsUceAdapter.java b/telephony/java/android/telephony/ims/RcsUceAdapter.java
index dd91026..7a1c092 100644
--- a/telephony/java/android/telephony/ims/RcsUceAdapter.java
+++ b/telephony/java/android/telephony/ims/RcsUceAdapter.java
@@ -28,10 +28,13 @@
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceSpecificException;
+import android.telephony.CarrierConfigManager;
+import android.telephony.SubscriptionManager;
import android.telephony.TelephonyFrameworkInitializer;
import android.telephony.ims.aidl.IImsRcsController;
import android.telephony.ims.aidl.IRcsUceControllerCallback;
import android.telephony.ims.aidl.IRcsUcePublishStateCallback;
+import android.telephony.ims.feature.RcsFeature;
import android.util.Log;
import java.lang.annotation.Retention;
@@ -417,7 +420,7 @@
* <p>
* After {@link CapabilitiesCallback#onComplete} or {@link CapabilitiesCallback#onError} has
* been called, the reference to this callback will be discarded on the service side.
- * @see #requestCapabilities(Executor, List, CapabilitiesCallback)
+ * @see #requestCapabilities(Collection, Executor, CapabilitiesCallback)
* @hide
*/
@SystemApi
@@ -464,10 +467,16 @@
}
/**
- * Request the User Capability Exchange capabilities for one or more contacts.
+ * Request the RCS capabilities for one or more contacts using RCS User Capability Exchange.
* <p>
- * This will return the cached capabilities of the contact and will not perform a capability
- * poll on the network unless there are contacts being queried with stale information.
+ * This API will first check a local cache for the requested numbers and return the cached
+ * RCS capabilities of each number if the cache exists and is not stale. If the cache for a
+ * number is stale or there is no cached information about the requested number, the device will
+ * then perform a query to the carrier's network to request the RCS capabilities of the
+ * requested numbers.
+ * <p>
+ * Depending on the number of requests being sent, this API may throttled internally as the
+ * operations are queued to be executed by the carrier's network.
* <p>
* Be sure to check the availability of this feature using
* {@link ImsRcsManager#isAvailable(int, int)} and ensuring
@@ -552,13 +561,15 @@
}
/**
- * Ignore the device cache and perform a capability discovery for one contact, also called
- * "availability fetch."
+ * Request the RCS capabilities for a phone number using User Capability Exchange.
* <p>
- * This will always perform a query to the network as long as requests are over the carrier
- * availability fetch throttling threshold. If too many network requests are sent too quickly,
- * #ERROR_TOO_MANY_REQUESTS will be returned.
- *
+ * Unlike {@link #requestCapabilities(Collection, Executor, CapabilitiesCallback)}, which caches
+ * the result received from the network for a certain amount of time and uses that cached result
+ * for subsequent requests for RCS capabilities of the same phone number, this API will always
+ * request the RCS capabilities of a contact from the carrier's network.
+ * <p>
+ * Depending on the number of requests, this API may throttled internally as the operations are
+ * queued to be executed by the carrier's network.
* <p>
* Be sure to check the availability of this feature using
* {@link ImsRcsManager#isAvailable(int, int)} and ensuring
@@ -680,7 +691,8 @@
* state updates for the subscription specified in {@link ImsManager@getRcsManager(subid)}.
* <p>
* Use {@link SubscriptionManager.OnSubscriptionsChangedListener} to listen to subscription
- * changed events and call {@link #unregisterPublishStateCallback} to clean up.
+ * changed events and call
+ * {@link #removeOnPublishStateChangedListener(OnPublishStateChangedListener)} to clean up.
* <p>
* The registered {@link OnPublishStateChangedListener} will also receive a callback when it is
* registered with the current publish state.
@@ -770,13 +782,23 @@
}
/**
- * The user’s setting for whether or not User Capability Exchange (UCE) is enabled for the
- * associated subscription.
+ * The setting for whether or not the user has opted in to the automatic refresh of the RCS
+ * capabilities associated with the contacts in the user's contact address book. By default,
+ * this setting is disabled and must be enabled after the user has seen the opt-in dialog shown
+ * by {@link ImsRcsManager#ACTION_SHOW_CAPABILITY_DISCOVERY_OPT_IN}.
+ * <p>
+ * If this feature is enabled, the device will periodically share the phone numbers of all of
+ * the contacts in the user's address book with the carrier to refresh the RCS capabilities
+ * cache associated with those contacts as the local cache becomes stale.
+ * <p>
+ * This setting will only enable this feature if
+ * {@link CarrierConfigManager.Ims#KEY_RCS_BULK_CAPABILITY_EXCHANGE_BOOL} is also enabled.
* <p>
* Note: This setting does not affect whether or not the device publishes its service
* capabilities if the subscription supports presence publication.
*
- * @return true if the user’s setting for UCE is enabled, false otherwise.
+ * @return true if the user has opted in for automatic refresh of the RCS capabilities of their
+ * contacts, false otherwise.
* @throws ImsException if the subscription associated with this instance of
* {@link RcsUceAdapter} is valid, but the ImsService associated with the subscription is not
* available. This can happen if the ImsService has crashed, for example, or if the subscription
@@ -802,18 +824,33 @@
}
/**
- * Change the user’s setting for whether or not UCE is enabled for the associated subscription.
+ * Change the user’s setting for whether or not the user has opted in to the automatic
+ * refresh of the RCS capabilities associated with the contacts in the user's contact address
+ * book. By default, this setting is disabled and must be enabled using this method after the
+ * user has seen the opt-in dialog shown by
+ * {@link ImsRcsManager#ACTION_SHOW_CAPABILITY_DISCOVERY_OPT_IN}.
* <p>
- * If an application Requires UCE, they will launch an Activity using the Intent
- * {@link ImsRcsManager#ACTION_SHOW_CAPABILITY_DISCOVERY_OPT_IN}, which will ask the user if
- * they wish to enable this feature. This setting should only be enabled after the user has
- * opted-in to capability exchange.
+ * If an application wishes to request that the user enable this feature, they must launch an
+ * Activity using the Intent {@link ImsRcsManager#ACTION_SHOW_CAPABILITY_DISCOVERY_OPT_IN},
+ * which will ask the user if they wish to enable this feature. This setting must only be
+ * enabled after the user has opted-in to this feature.
+ * <p>
+ * This must not affect the
+ * {@link #requestCapabilities(Collection, Executor, CapabilitiesCallback)} or
+ * {@link #requestAvailability(Uri, Executor, CapabilitiesCallback)} API,
+ * as those APIs are still required for per-contact RCS capability queries of phone numbers
+ * required for operations such as placing a Video Telephony call or starting an RCS chat
+ * session.
+ * <p>
+ * This setting will only enable this feature if
+ * {@link CarrierConfigManager.Ims#KEY_RCS_BULK_CAPABILITY_EXCHANGE_BOOL} is also enabled.
* <p>
* Note: This setting does not affect whether or not the device publishes its service
* capabilities if the subscription supports presence publication.
*
- * @param isEnabled the user's setting for whether or not they wish for User
- * Capability Exchange to be enabled.
+ * @param isEnabled true if the user has opted in for automatic refresh of the RCS capabilities
+ * of their contacts, or false if they have chosen to opt-out. By default this
+ * setting is disabled.
* @throws ImsException if the subscription associated with this instance of
* {@link RcsUceAdapter} is valid, but the ImsService associated with the subscription is not
* available. This can happen if the ImsService has crashed, for example, or if the subscription
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 4cd59a2..91ecbf0 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -2352,6 +2352,12 @@
void setActiveDeviceToDeviceTransport(String transport);
/**
+ * Forces Device to Device communication to be enabled, even if the device config has it
+ * disabled.
+ */
+ void setDeviceToDeviceForceEnabled(boolean isForceEnabled);
+
+ /**
* Gets the config of RCS VoLTE single registration enabled for the carrier/subscription.
*/
boolean getCarrierSingleRegistrationEnabled(int subId);
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index 1d1eddf..fe8e671 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -497,6 +497,9 @@
int RIL_REQUEST_ENABLE_MODEM = 146;
int RIL_REQUEST_GET_MODEM_STATUS = 147;
int RIL_REQUEST_CDMA_SEND_SMS_EXPECT_MORE = 148;
+ int RIL_REQUEST_GET_SIM_PHONEBOOK_CAPACITY = 149;
+ int RIL_REQUEST_GET_SIM_PHONEBOOK_RECORDS = 150;
+ int RIL_REQUEST_UPDATE_SIM_PHONEBOOK_RECORD = 151;
/* The following requests are not defined in RIL.h */
int RIL_REQUEST_HAL_NON_RIL_BASE = 200;
@@ -583,6 +586,8 @@
int RIL_UNSOL_NETWORK_SCAN_RESULT = 1049;
int RIL_UNSOL_KEEPALIVE_STATUS = 1050;
int RIL_UNSOL_UNTHROTTLE_APN = 1052;
+ int RIL_UNSOL_RESPONSE_SIM_PHONEBOOK_CHANGED = 1053;
+ int RIL_UNSOL_RESPONSE_SIM_PHONEBOOK_RECORDS_RECEIVED = 1054;
/* The following unsols are not defined in RIL.h */
int RIL_UNSOL_HAL_NON_RIL_BASE = 1100;
diff --git a/tests/Input/src/com/android/test/input/InputEventSenderAndReceiverTest.kt b/tests/Input/src/com/android/test/input/InputEventSenderAndReceiverTest.kt
index fc1d839..014efc2 100644
--- a/tests/Input/src/com/android/test/input/InputEventSenderAndReceiverTest.kt
+++ b/tests/Input/src/com/android/test/input/InputEventSenderAndReceiverTest.kt
@@ -145,4 +145,21 @@
val received = mSender.getTimeline()
assertEquals(sent, received)
}
+
+ // If an invalid timeline is sent, the channel should get closed. This helps surface any
+ // app-originating bugs early, and forces the work-around to happen in the early stages of the
+ // event processing.
+ @Test
+ fun testSendAndReceiveInvalidTimeline() {
+ val sent = TestInputEventSender.Timeline(
+ inputEventId = 1, gpuCompletedTime = 3, presentTime = 2)
+ mReceiver.reportTimeline(sent.inputEventId, sent.gpuCompletedTime, sent.presentTime)
+ val received = mSender.getTimeline()
+ assertEquals(null, received)
+ // Sender will no longer receive callbacks for this fd, even if receiver sends a valid
+ // timeline later
+ mReceiver.reportTimeline(2 /*inputEventId*/, 3 /*gpuCompletedTime*/, 4 /*presentTime*/)
+ val receivedSecondTimeline = mSender.getTimeline()
+ assertEquals(null, receivedSecondTimeline)
+ }
}
diff --git a/tests/UpdatableSystemFontTest/src/com/android/updatablesystemfont/UpdatableSystemFontTest.java b/tests/UpdatableSystemFontTest/src/com/android/updatablesystemfont/UpdatableSystemFontTest.java
index 898b8d4..80b0dfe 100644
--- a/tests/UpdatableSystemFontTest/src/com/android/updatablesystemfont/UpdatableSystemFontTest.java
+++ b/tests/UpdatableSystemFontTest/src/com/android/updatablesystemfont/UpdatableSystemFontTest.java
@@ -20,6 +20,7 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.assertThrows;
import static org.junit.Assume.assumeTrue;
import static java.util.concurrent.TimeUnit.SECONDS;
@@ -56,6 +57,11 @@
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.regex.Pattern;
/**
* Tests if fonts can be updated by {@link FontManager} API.
@@ -95,6 +101,12 @@
EMOJI_RENDERING_TEST_APP_ID + "/.EmojiRenderingTestActivity";
private static final long ACTIVITY_TIMEOUT_MILLIS = SECONDS.toMillis(10);
+ 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/");
+ private static final Pattern PATTERN_SYSTEM_FONT_FILES =
+ Pattern.compile("^/(system|product)/fonts/");
+
private String mKeyId;
private FontManager mFontManager;
@@ -236,6 +248,45 @@
assertThat(fontPathAfterReboot).isEqualTo(fontPath);
}
+ @Test
+ public void fdLeakTest() throws Exception {
+ long originalOpenFontCount =
+ countMatch(getOpenFiles("system_server"), PATTERN_FONT_FILES);
+ Pattern patternEmojiVPlus1 =
+ Pattern.compile(Pattern.quote(TEST_NOTO_COLOR_EMOJI_VPLUS1_TTF));
+ for (int i = 0; i < 10; i++) {
+ assertThat(updateFontFile(
+ TEST_NOTO_COLOR_EMOJI_VPLUS1_TTF, TEST_NOTO_COLOR_EMOJI_VPLUS1_TTF_FSV_SIG))
+ .isEqualTo(FontManager.RESULT_SUCCESS);
+ List<String> openFiles = getOpenFiles("system_server");
+ for (Pattern p : Arrays.asList(PATTERN_FONT_FILES, PATTERN_SYSTEM_FONT_FILES,
+ PATTERN_DATA_FONT_FILES, PATTERN_TMP_FILES)) {
+ Log.i(TAG, String.format("num of %s: %d", p, countMatch(openFiles, p)));
+ }
+ // system_server should not keep /data/fonts files open.
+ assertThat(countMatch(openFiles, PATTERN_DATA_FONT_FILES)).isEqualTo(0);
+ // system_server should not keep passed FD open.
+ assertThat(countMatch(openFiles, patternEmojiVPlus1)).isEqualTo(0);
+ // The number of open font FD should not increase.
+ assertThat(countMatch(openFiles, PATTERN_FONT_FILES))
+ .isAtMost(originalOpenFontCount);
+ }
+ }
+
+ @Test
+ public void fdLeakTest_withoutPermission() throws Exception {
+ Pattern patternEmojiVPlus1 =
+ Pattern.compile(Pattern.quote(TEST_NOTO_COLOR_EMOJI_VPLUS1_TTF));
+ byte[] signature = Files.readAllBytes(Paths.get(TEST_NOTO_COLOR_EMOJI_VPLUS1_TTF_FSV_SIG));
+ try (ParcelFileDescriptor fd = ParcelFileDescriptor.open(
+ new File(TEST_NOTO_COLOR_EMOJI_VPLUS1_TTF), MODE_READ_ONLY)) {
+ assertThrows(SecurityException.class,
+ () -> updateFontFileWithoutPermission(fd, signature, 0));
+ }
+ List<String> openFiles = getOpenFiles("system_server");
+ assertThat(countMatch(openFiles, patternEmojiVPlus1)).isEqualTo(0);
+ }
+
private static String insertCert(String certPath) throws Exception {
Pair<String, String> result;
try (InputStream is = new FileInputStream(certPath)) {
@@ -253,16 +304,21 @@
try (ParcelFileDescriptor fd =
ParcelFileDescriptor.open(new File(fontPath), MODE_READ_ONLY)) {
return SystemUtil.runWithShellPermissionIdentity(() -> {
- FontConfig fontConfig = mFontManager.getFontConfig();
- return mFontManager.updateFontFamily(
- new FontFamilyUpdateRequest.Builder()
- .addFontFileUpdateRequest(new FontFileUpdateRequest(fd, signature))
- .build(),
- fontConfig.getConfigVersion());
+ int configVersion = mFontManager.getFontConfig().getConfigVersion();
+ return updateFontFileWithoutPermission(fd, signature, configVersion);
});
}
}
+ private int updateFontFileWithoutPermission(ParcelFileDescriptor fd, byte[] signature,
+ int configVersion) {
+ return mFontManager.updateFontFamily(
+ new FontFamilyUpdateRequest.Builder()
+ .addFontFileUpdateRequest(new FontFileUpdateRequest(fd, signature))
+ .build(),
+ configVersion);
+ }
+
private String getFontPath(String psName) {
return SystemUtil.runWithShellPermissionIdentity(() -> {
FontConfig fontConfig = mFontManager.getFontConfig();
@@ -338,7 +394,37 @@
return !expectCommandToSucceed(cmd).trim().isEmpty();
}
+ private static List<String> getOpenFiles(String appId) throws Exception {
+ String pid = pidOf(appId);
+ if (pid.isEmpty()) {
+ return Collections.emptyList();
+ }
+ String cmd = String.format("lsof -p %s", pid);
+ String out = expectCommandToSucceed(cmd);
+ List<String> paths = new ArrayList<>();
+ boolean first = true;
+ for (String line : out.split("\n")) {
+ // Skip the header.
+ if (first) {
+ first = false;
+ continue;
+ }
+ String[] records = line.split(" ");
+ if (records.length > 0) {
+ paths.add(records[records.length - 1]);
+ }
+ }
+ return paths;
+ }
+
private static String pidOf(String appId) throws Exception {
return expectCommandToSucceed("pidof " + appId).trim();
}
+
+ private static long countMatch(List<String> paths, Pattern pattern) {
+ // Note: asPredicate() returns true for partial matching.
+ return paths.stream()
+ .filter(pattern.asPredicate())
+ .count();
+ }
}
diff --git a/tests/vcn/java/android/net/vcn/VcnTransportInfoTest.java b/tests/vcn/java/android/net/vcn/VcnTransportInfoTest.java
index 00a0bff..19df3c7 100644
--- a/tests/vcn/java/android/net/vcn/VcnTransportInfoTest.java
+++ b/tests/vcn/java/android/net/vcn/VcnTransportInfoTest.java
@@ -17,7 +17,6 @@
package android.net.vcn;
import static android.net.NetworkCapabilities.REDACT_FOR_ACCESS_FINE_LOCATION;
-import static android.net.NetworkCapabilities.REDACT_FOR_LOCAL_MAC_ADDRESS;
import static android.net.NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS;
import static android.net.NetworkCapabilities.REDACT_NONE;
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
@@ -26,12 +25,15 @@
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNull;
+import android.net.NetworkCapabilities;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.os.Parcel;
import org.junit.Test;
+import java.util.Arrays;
+
public class VcnTransportInfoTest {
private static final int SUB_ID = 1;
private static final int NETWORK_ID = 5;
@@ -56,6 +58,19 @@
}
@Test
+ public void testMakeCopyRedactForNetworkSettings() {
+ for (VcnTransportInfo info : Arrays.asList(CELL_UNDERLYING_INFO, WIFI_UNDERLYING_INFO)) {
+ assertEquals(
+ INVALID_SUBSCRIPTION_ID,
+ ((VcnTransportInfo) info.makeCopy(REDACT_FOR_NETWORK_SETTINGS))
+ .getSubId());
+ assertNull(
+ ((VcnTransportInfo) info.makeCopy(REDACT_FOR_NETWORK_SETTINGS))
+ .getWifiInfo());
+ }
+ }
+
+ @Test
public void testMakeCopyRedactForAccessFineLocation() {
assertEquals(
SUB_ID,
@@ -75,11 +90,20 @@
}
@Test
- public void testApplicableRedactions() {
- assertEquals(REDACT_NONE, CELL_UNDERLYING_INFO.getApplicableRedactions());
- assertEquals(REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_LOCAL_MAC_ADDRESS
- | REDACT_FOR_NETWORK_SETTINGS,
- WIFI_UNDERLYING_INFO.getApplicableRedactions());
+ public void testParcelUnparcel() {
+ verifyParcelingIsNull(CELL_UNDERLYING_INFO);
+ verifyParcelingIsNull(WIFI_UNDERLYING_INFO);
+ }
+
+ private void verifyParcelingIsNull(VcnTransportInfo vcnTransportInfo) {
+ VcnTransportInfo redacted = (VcnTransportInfo) vcnTransportInfo.makeCopy(
+ NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS);
+
+ Parcel parcel = Parcel.obtain();
+ redacted.writeToParcel(parcel, 0 /* flags */);
+ parcel.setDataPosition(0);
+
+ assertNull(VcnTransportInfo.CREATOR.createFromParcel(parcel));
}
@Test
diff --git a/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java b/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java
index 528f240..ca74638 100644
--- a/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java
+++ b/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java
@@ -88,13 +88,13 @@
private static final SubscriptionInfo TEST_SUBINFO_2 = mock(SubscriptionInfo.class);
private static final Map<ParcelUuid, Set<String>> TEST_PRIVILEGED_PACKAGES =
Collections.singletonMap(TEST_PARCEL_UUID, Collections.singleton(PACKAGE_NAME));
- private static final Map<Integer, ParcelUuid> TEST_SUBID_TO_GROUP_MAP;
+ private static final Map<Integer, SubscriptionInfo> TEST_SUBID_TO_INFO_MAP;
static {
- final Map<Integer, ParcelUuid> subIdToGroupMap = new HashMap<>();
- subIdToGroupMap.put(TEST_SUBSCRIPTION_ID_1, TEST_PARCEL_UUID);
- subIdToGroupMap.put(TEST_SUBSCRIPTION_ID_2, TEST_PARCEL_UUID);
- TEST_SUBID_TO_GROUP_MAP = Collections.unmodifiableMap(subIdToGroupMap);
+ final Map<Integer, SubscriptionInfo> subIdToGroupMap = new HashMap<>();
+ subIdToGroupMap.put(TEST_SUBSCRIPTION_ID_1, TEST_SUBINFO_1);
+ subIdToGroupMap.put(TEST_SUBSCRIPTION_ID_2, TEST_SUBINFO_2);
+ TEST_SUBID_TO_INFO_MAP = Collections.unmodifiableMap(subIdToGroupMap);
}
@NonNull private final Context mContext;
@@ -190,13 +190,13 @@
private TelephonySubscriptionSnapshot buildExpectedSnapshot(
Map<ParcelUuid, Set<String>> privilegedPackages) {
- return buildExpectedSnapshot(TEST_SUBID_TO_GROUP_MAP, privilegedPackages);
+ return buildExpectedSnapshot(TEST_SUBID_TO_INFO_MAP, privilegedPackages);
}
private TelephonySubscriptionSnapshot buildExpectedSnapshot(
- Map<Integer, ParcelUuid> subIdToGroupMap,
+ Map<Integer, SubscriptionInfo> subIdToInfoMap,
Map<ParcelUuid, Set<String>> privilegedPackages) {
- return new TelephonySubscriptionSnapshot(subIdToGroupMap, privilegedPackages);
+ return new TelephonySubscriptionSnapshot(subIdToInfoMap, privilegedPackages);
}
private void verifyNoActiveSubscriptions() {
@@ -371,7 +371,7 @@
@Test
public void testTelephonySubscriptionSnapshotGetGroupForSubId() throws Exception {
final TelephonySubscriptionSnapshot snapshot =
- new TelephonySubscriptionSnapshot(TEST_SUBID_TO_GROUP_MAP, emptyMap());
+ new TelephonySubscriptionSnapshot(TEST_SUBID_TO_INFO_MAP, emptyMap());
assertEquals(TEST_PARCEL_UUID, snapshot.getGroupForSubId(TEST_SUBSCRIPTION_ID_1));
assertEquals(TEST_PARCEL_UUID, snapshot.getGroupForSubId(TEST_SUBSCRIPTION_ID_2));
@@ -380,7 +380,7 @@
@Test
public void testTelephonySubscriptionSnapshotGetAllSubIdsInGroup() throws Exception {
final TelephonySubscriptionSnapshot snapshot =
- new TelephonySubscriptionSnapshot(TEST_SUBID_TO_GROUP_MAP, emptyMap());
+ new TelephonySubscriptionSnapshot(TEST_SUBID_TO_INFO_MAP, emptyMap());
assertEquals(
new ArraySet<>(Arrays.asList(TEST_SUBSCRIPTION_ID_1, TEST_SUBSCRIPTION_ID_2)),
diff --git a/tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java b/tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java
index 0b72cd9..a36fd79 100644
--- a/tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java
+++ b/tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java
@@ -42,12 +42,14 @@
import android.net.TelephonyNetworkSpecifier;
import android.os.ParcelUuid;
import android.os.test.TestLooper;
+import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionInfo;
+import android.telephony.TelephonyManager;
import android.util.ArraySet;
import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
import com.android.server.vcn.UnderlyingNetworkTracker.NetworkBringupCallback;
-import com.android.server.vcn.UnderlyingNetworkTracker.RouteSelectionCallback;
+import com.android.server.vcn.UnderlyingNetworkTracker.UnderlyingNetworkListener;
import com.android.server.vcn.UnderlyingNetworkTracker.UnderlyingNetworkRecord;
import com.android.server.vcn.UnderlyingNetworkTracker.UnderlyingNetworkTrackerCallback;
@@ -98,11 +100,13 @@
@Mock private Context mContext;
@Mock private VcnNetworkProvider mVcnNetworkProvider;
@Mock private ConnectivityManager mConnectivityManager;
+ @Mock private TelephonyManager mTelephonyManager;
+ @Mock private CarrierConfigManager mCarrierConfigManager;
@Mock private TelephonySubscriptionSnapshot mSubscriptionSnapshot;
@Mock private UnderlyingNetworkTrackerCallback mNetworkTrackerCb;
@Mock private Network mNetwork;
- @Captor private ArgumentCaptor<RouteSelectionCallback> mRouteSelectionCallbackCaptor;
+ @Captor private ArgumentCaptor<UnderlyingNetworkListener> mUnderlyingNetworkListenerCaptor;
private TestLooper mTestLooper;
private VcnContext mVcnContext;
@@ -127,6 +131,13 @@
mConnectivityManager,
Context.CONNECTIVITY_SERVICE,
ConnectivityManager.class);
+ setupSystemService(
+ mContext, mTelephonyManager, Context.TELEPHONY_SERVICE, TelephonyManager.class);
+ setupSystemService(
+ mContext,
+ mCarrierConfigManager,
+ Context.CARRIER_CONFIG_SERVICE,
+ CarrierConfigManager.class);
when(mSubscriptionSnapshot.getAllSubIdsInGroup(eq(SUB_GROUP))).thenReturn(INITIAL_SUB_IDS);
@@ -163,26 +174,26 @@
@Test
public void testNetworkCallbacksRegisteredOnStartupForTestMode() {
+ final ConnectivityManager cm = mock(ConnectivityManager.class);
+ setupSystemService(mContext, cm, Context.CONNECTIVITY_SERVICE, ConnectivityManager.class);
final VcnContext vcnContext =
- spy(
- new VcnContext(
- mContext,
- mTestLooper.getLooper(),
- mVcnNetworkProvider,
- true /* isInTestMode */));
+ new VcnContext(
+ mContext,
+ mTestLooper.getLooper(),
+ mVcnNetworkProvider,
+ true /* isInTestMode */);
- mUnderlyingNetworkTracker =
- new UnderlyingNetworkTracker(
- vcnContext,
- SUB_GROUP,
- mSubscriptionSnapshot,
- Collections.singleton(NetworkCapabilities.NET_CAPABILITY_INTERNET),
- mNetworkTrackerCb);
+ new UnderlyingNetworkTracker(
+ vcnContext,
+ SUB_GROUP,
+ mSubscriptionSnapshot,
+ Collections.singleton(NetworkCapabilities.NET_CAPABILITY_INTERNET),
+ mNetworkTrackerCb);
- verify(mConnectivityManager)
- .requestBackgroundNetwork(
+ verify(cm)
+ .registerNetworkCallback(
eq(getTestNetworkRequest(INITIAL_SUB_IDS)),
- any(RouteSelectionCallback.class),
+ any(UnderlyingNetworkListener.class),
any());
}
@@ -200,9 +211,19 @@
}
verify(mConnectivityManager)
- .requestBackgroundNetwork(
+ .registerNetworkCallback(
eq(getRouteSelectionRequest(expectedSubIds)),
- any(RouteSelectionCallback.class),
+ any(UnderlyingNetworkListener.class),
+ any());
+ verify(mConnectivityManager)
+ .registerNetworkCallback(
+ eq(getWifiEntryRssiThresholdRequest(expectedSubIds)),
+ any(NetworkBringupCallback.class),
+ any());
+ verify(mConnectivityManager)
+ .registerNetworkCallback(
+ eq(getWifiExitRssiThresholdRequest(expectedSubIds)),
+ any(NetworkBringupCallback.class),
any());
}
@@ -218,9 +239,10 @@
mUnderlyingNetworkTracker.updateSubscriptionSnapshot(subscriptionUpdate);
// verify that initially-filed bringup requests are unregistered (cell + wifi)
- verify(mConnectivityManager, times(INITIAL_SUB_IDS.size() + 1))
+ verify(mConnectivityManager, times(INITIAL_SUB_IDS.size() + 3))
.unregisterNetworkCallback(any(NetworkBringupCallback.class));
- verify(mConnectivityManager).unregisterNetworkCallback(any(RouteSelectionCallback.class));
+ verify(mConnectivityManager)
+ .unregisterNetworkCallback(any(UnderlyingNetworkListener.class));
verifyNetworkRequestsRegistered(UPDATED_SUB_IDS);
}
@@ -231,6 +253,24 @@
.build();
}
+ private NetworkRequest getWifiEntryRssiThresholdRequest(Set<Integer> netCapsSubIds) {
+ // TODO (b/187991063): Add tests for carrier-config based thresholds
+ return getExpectedRequestBase()
+ .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+ .setSubscriptionIds(netCapsSubIds)
+ .setSignalStrength(UnderlyingNetworkTracker.WIFI_ENTRY_RSSI_THRESHOLD_DEFAULT)
+ .build();
+ }
+
+ private NetworkRequest getWifiExitRssiThresholdRequest(Set<Integer> netCapsSubIds) {
+ // TODO (b/187991063): Add tests for carrier-config based thresholds
+ return getExpectedRequestBase()
+ .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+ .setSubscriptionIds(netCapsSubIds)
+ .setSignalStrength(UnderlyingNetworkTracker.WIFI_EXIT_RSSI_THRESHOLD_DEFAULT)
+ .build();
+ }
+
private NetworkRequest getCellRequestForSubId(int subId) {
return getExpectedRequestBase()
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
@@ -239,7 +279,11 @@
}
private NetworkRequest getRouteSelectionRequest(Set<Integer> netCapsSubIds) {
- return getExpectedRequestBase().setSubscriptionIds(netCapsSubIds).build();
+ return getExpectedRequestBase()
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED)
+ .setSubscriptionIds(netCapsSubIds)
+ .build();
}
private NetworkRequest getTestNetworkRequest(Set<Integer> netCapsSubIds) {
@@ -265,11 +309,12 @@
public void testTeardown() {
mUnderlyingNetworkTracker.teardown();
- // Expect 3 NetworkBringupCallbacks to be unregistered: 1 for WiFi and 2 for Cellular (1x
- // for each subId)
- verify(mConnectivityManager, times(3))
+ // Expect 5 NetworkBringupCallbacks to be unregistered: 1 for WiFi, 2 for Cellular (1x for
+ // each subId), and 1 for each of the Wifi signal strength thresholds
+ verify(mConnectivityManager, times(5))
.unregisterNetworkCallback(any(NetworkBringupCallback.class));
- verify(mConnectivityManager).unregisterNetworkCallback(any(RouteSelectionCallback.class));
+ verify(mConnectivityManager)
+ .unregisterNetworkCallback(any(UnderlyingNetworkListener.class));
}
@Test
@@ -302,19 +347,19 @@
verifyRegistrationOnAvailableAndGetCallback();
}
- private RouteSelectionCallback verifyRegistrationOnAvailableAndGetCallback() {
+ private UnderlyingNetworkListener verifyRegistrationOnAvailableAndGetCallback() {
return verifyRegistrationOnAvailableAndGetCallback(INITIAL_NETWORK_CAPABILITIES);
}
- private RouteSelectionCallback verifyRegistrationOnAvailableAndGetCallback(
+ private UnderlyingNetworkListener verifyRegistrationOnAvailableAndGetCallback(
NetworkCapabilities networkCapabilities) {
verify(mConnectivityManager)
- .requestBackgroundNetwork(
+ .registerNetworkCallback(
eq(getRouteSelectionRequest(INITIAL_SUB_IDS)),
- mRouteSelectionCallbackCaptor.capture(),
+ mUnderlyingNetworkListenerCaptor.capture(),
any());
- RouteSelectionCallback cb = mRouteSelectionCallbackCaptor.getValue();
+ UnderlyingNetworkListener cb = mUnderlyingNetworkListenerCaptor.getValue();
cb.onAvailable(mNetwork);
cb.onCapabilitiesChanged(mNetwork, networkCapabilities);
cb.onLinkPropertiesChanged(mNetwork, INITIAL_LINK_PROPERTIES);
@@ -332,7 +377,7 @@
@Test
public void testRecordTrackerCallbackNotifiedForNetworkCapabilitiesChange() {
- RouteSelectionCallback cb = verifyRegistrationOnAvailableAndGetCallback();
+ UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback();
cb.onCapabilitiesChanged(mNetwork, UPDATED_NETWORK_CAPABILITIES);
@@ -347,7 +392,7 @@
@Test
public void testRecordTrackerCallbackNotifiedForLinkPropertiesChange() {
- RouteSelectionCallback cb = verifyRegistrationOnAvailableAndGetCallback();
+ UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback();
cb.onLinkPropertiesChanged(mNetwork, UPDATED_LINK_PROPERTIES);
@@ -362,7 +407,7 @@
@Test
public void testRecordTrackerCallbackNotifiedForNetworkSuspended() {
- RouteSelectionCallback cb = verifyRegistrationOnAvailableAndGetCallback();
+ UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback();
cb.onCapabilitiesChanged(mNetwork, SUSPENDED_NETWORK_CAPABILITIES);
@@ -381,7 +426,7 @@
@Test
public void testRecordTrackerCallbackNotifiedForNetworkResumed() {
- RouteSelectionCallback cb =
+ UnderlyingNetworkListener cb =
verifyRegistrationOnAvailableAndGetCallback(SUSPENDED_NETWORK_CAPABILITIES);
cb.onCapabilitiesChanged(mNetwork, INITIAL_NETWORK_CAPABILITIES);
@@ -401,7 +446,7 @@
@Test
public void testRecordTrackerCallbackNotifiedForBlocked() {
- RouteSelectionCallback cb = verifyRegistrationOnAvailableAndGetCallback();
+ UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback();
cb.onBlockedStatusChanged(mNetwork, true /* isBlocked */);
@@ -416,7 +461,7 @@
@Test
public void testRecordTrackerCallbackNotifiedForNetworkLoss() {
- RouteSelectionCallback cb = verifyRegistrationOnAvailableAndGetCallback();
+ UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback();
cb.onLost(mNetwork);
@@ -425,7 +470,7 @@
@Test
public void testRecordTrackerCallbackIgnoresDuplicateRecord() {
- RouteSelectionCallback cb = verifyRegistrationOnAvailableAndGetCallback();
+ UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback();
cb.onCapabilitiesChanged(mNetwork, INITIAL_NETWORK_CAPABILITIES);
@@ -433,4 +478,6 @@
// UnderlyingNetworkRecord does not actually change
verifyNoMoreInteractions(mNetworkTrackerCb);
}
+
+ // TODO (b/187991063): Add tests for network prioritization
}
diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java
index 1ecb4c9..c747bc0 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java
@@ -54,6 +54,7 @@
import android.os.ParcelUuid;
import android.os.PowerManager;
import android.os.test.TestLooper;
+import android.telephony.SubscriptionInfo;
import com.android.internal.util.State;
import com.android.internal.util.WakeupMessage;
@@ -73,6 +74,12 @@
public class VcnGatewayConnectionTestBase {
protected static final ParcelUuid TEST_SUB_GRP = new ParcelUuid(UUID.randomUUID());
+ protected static final SubscriptionInfo TEST_SUB_INFO = mock(SubscriptionInfo.class);
+
+ static {
+ doReturn(TEST_SUB_GRP).when(TEST_SUB_INFO).getGroupUuid();
+ }
+
protected static final InetAddress TEST_DNS_ADDR =
InetAddresses.parseNumericAddress("2001:DB8:0:1::");
protected static final InetAddress TEST_DNS_ADDR_2 =
@@ -116,7 +123,7 @@
protected static final TelephonySubscriptionSnapshot TEST_SUBSCRIPTION_SNAPSHOT =
new TelephonySubscriptionSnapshot(
- Collections.singletonMap(TEST_SUB_ID, TEST_SUB_GRP), Collections.EMPTY_MAP);
+ Collections.singletonMap(TEST_SUB_ID, TEST_SUB_INFO), Collections.EMPTY_MAP);
@NonNull protected final Context mContext;
@NonNull protected final TestLooper mTestLooper;
diff --git a/tools/aapt/pseudolocalize.cpp b/tools/aapt/pseudolocalize.cpp
index 5c47e0f..4e8dcb1 100644
--- a/tools/aapt/pseudolocalize.cpp
+++ b/tools/aapt/pseudolocalize.cpp
@@ -194,7 +194,8 @@
break;
}
}
- result.remove(length + ext, 0);
+ // Just keep the first length + ext characters
+ result = String16(result, length + ext);
}
return result;
}