Merge "Expand JS documentation." into sc-dev
diff --git a/apex/appsearch/framework/api/current.txt b/apex/appsearch/framework/api/current.txt
index 7441b0f..4dff436 100644
--- a/apex/appsearch/framework/api/current.txt
+++ b/apex/appsearch/framework/api/current.txt
@@ -289,14 +289,16 @@
public final class SearchResult {
method @NonNull public String getDatabaseName();
method @NonNull public android.app.appsearch.GenericDocument getGenericDocument();
- method @NonNull public java.util.List<android.app.appsearch.SearchResult.MatchInfo> getMatches();
+ method @NonNull public java.util.List<android.app.appsearch.SearchResult.MatchInfo> getMatchInfos();
+ method @Deprecated @NonNull public java.util.List<android.app.appsearch.SearchResult.MatchInfo> getMatches();
method @NonNull public String getPackageName();
method public double getRankingSignal();
}
public static final class SearchResult.Builder {
ctor public SearchResult.Builder(@NonNull String, @NonNull String);
- method @NonNull public android.app.appsearch.SearchResult.Builder addMatch(@NonNull android.app.appsearch.SearchResult.MatchInfo);
+ method @Deprecated @NonNull public android.app.appsearch.SearchResult.Builder addMatch(@NonNull android.app.appsearch.SearchResult.MatchInfo);
+ method @NonNull public android.app.appsearch.SearchResult.Builder addMatchInfo(@NonNull android.app.appsearch.SearchResult.MatchInfo);
method @NonNull public android.app.appsearch.SearchResult build();
method @NonNull public android.app.appsearch.SearchResult.Builder setGenericDocument(@NonNull android.app.appsearch.GenericDocument);
method @NonNull public android.app.appsearch.SearchResult.Builder setRankingSignal(double);
diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchMigrationHelper.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchMigrationHelper.java
index 4357905..0089c6d 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchMigrationHelper.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchMigrationHelper.java
@@ -30,8 +30,6 @@
import android.os.RemoteException;
import android.util.ArraySet;
-import com.android.internal.infra.AndroidFuture;
-
import java.io.Closeable;
import java.io.DataInputStream;
import java.io.DataOutputStream;
@@ -43,6 +41,7 @@
import java.util.List;
import java.util.Objects;
import java.util.Set;
+import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
/**
@@ -95,7 +94,7 @@
File queryFile = File.createTempFile(/*prefix=*/"appsearch", /*suffix=*/null);
try (ParcelFileDescriptor fileDescriptor =
ParcelFileDescriptor.open(queryFile, MODE_WRITE_ONLY)) {
- AndroidFuture<AppSearchResult<Void>> androidFuture = new AndroidFuture<>();
+ CompletableFuture<AppSearchResult<Void>> future = new CompletableFuture<>();
mService.writeQueryResultsToFile(mPackageName, mDatabaseName,
fileDescriptor,
/*queryExpression=*/ "",
@@ -106,11 +105,11 @@
mUserId,
new IAppSearchResultCallback.Stub() {
@Override
- public void onResult(AppSearchResult result) throws RemoteException {
- androidFuture.complete(result);
+ public void onResult(AppSearchResult result) {
+ future.complete(result);
}
});
- AppSearchResult<Void> result = androidFuture.get();
+ AppSearchResult<Void> result = future.get();
if (!result.isSuccess()) {
throw new AppSearchException(result.getResultCode(), result.getErrorMessage());
}
@@ -142,15 +141,15 @@
}
try (ParcelFileDescriptor fileDescriptor =
ParcelFileDescriptor.open(mMigratedFile, MODE_READ_ONLY)) {
- AndroidFuture<AppSearchResult<List<Bundle>>> androidFuture = new AndroidFuture<>();
+ CompletableFuture<AppSearchResult<List<Bundle>>> future = new CompletableFuture<>();
mService.putDocumentsFromFile(mPackageName, mDatabaseName, fileDescriptor, mUserId,
new IAppSearchResultCallback.Stub() {
@Override
- public void onResult(AppSearchResult result) throws RemoteException {
- androidFuture.complete(result);
+ public void onResult(AppSearchResult result) {
+ future.complete(result);
}
});
- AppSearchResult<List<Bundle>> result = androidFuture.get();
+ AppSearchResult<List<Bundle>> result = future.get();
if (!result.isSuccess()) {
return AppSearchResult.newFailedResult(result);
}
diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java
index 1e0d205..64ac63c 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java
@@ -28,7 +28,6 @@
import android.util.ArraySet;
import android.util.Log;
-import com.android.internal.infra.AndroidFuture;
import com.android.internal.util.Preconditions;
import java.io.Closeable;
@@ -37,6 +36,7 @@
import java.util.Map;
import java.util.Objects;
import java.util.Set;
+import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
@@ -708,8 +708,8 @@
try {
// Migration process
// 1. Validate and retrieve all active migrators.
- AndroidFuture<AppSearchResult<GetSchemaResponse>> getSchemaFuture =
- new AndroidFuture<>();
+ CompletableFuture<AppSearchResult<GetSchemaResponse>> getSchemaFuture =
+ new CompletableFuture<>();
getSchema(callbackExecutor, getSchemaFuture::complete);
AppSearchResult<GetSchemaResponse> getSchemaResult = getSchemaFuture.get();
if (!getSchemaResult.isSuccess()) {
@@ -733,7 +733,8 @@
// 2. SetSchema with forceOverride=false, to retrieve the list of
// incompatible/deleted types.
- AndroidFuture<AppSearchResult<Bundle>> setSchemaFuture = new AndroidFuture<>();
+ CompletableFuture<AppSearchResult<Bundle>> setSchemaFuture =
+ new CompletableFuture<>();
mService.setSchema(
mPackageName,
mDatabaseName,
@@ -781,8 +782,8 @@
// failed.
if (!setSchemaResponse.getIncompatibleTypes().isEmpty()
|| !setSchemaResponse.getDeletedTypes().isEmpty()) {
- AndroidFuture<AppSearchResult<Bundle>> setSchema2Future =
- new AndroidFuture<>();
+ CompletableFuture<AppSearchResult<Bundle>> setSchema2Future =
+ new CompletableFuture<>();
// only trigger second setSchema() call if the first one is fail.
mService.setSchema(
mPackageName,
diff --git a/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl b/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl
index 17f724b..507bd68 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl
+++ b/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl
@@ -17,14 +17,9 @@
import android.os.Bundle;
-import android.app.appsearch.AppSearchBatchResult;
-import android.app.appsearch.AppSearchResult;
import android.app.appsearch.IAppSearchBatchResultCallback;
import android.app.appsearch.IAppSearchResultCallback;
import android.os.ParcelFileDescriptor;
-import com.android.internal.infra.AndroidFuture;
-
-parcelable SearchResults;
/** {@hide} */
interface IAppSearchManager {
diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/GenericDocument.java b/apex/appsearch/framework/java/external/android/app/appsearch/GenericDocument.java
index 85018ad..2e42749 100644
--- a/apex/appsearch/framework/java/external/android/app/appsearch/GenericDocument.java
+++ b/apex/appsearch/framework/java/external/android/app/appsearch/GenericDocument.java
@@ -843,6 +843,20 @@
}
}
+ /**
+ * Copies the contents of this {@link GenericDocument} into a new {@link
+ * GenericDocument.Builder}.
+ *
+ * <p>The returned builder is a deep copy whose data is separate from this document.
+ *
+ * @hide
+ */
+ @NonNull
+ public GenericDocument.Builder<GenericDocument.Builder<?>> toBuilder() {
+ Bundle clonedBundle = BundleUtil.deepCopy(mBundle);
+ return new GenericDocument.Builder<>(clonedBundle);
+ }
+
@Override
public boolean equals(@Nullable Object other) {
if (this == other) {
@@ -936,8 +950,8 @@
@SuppressLint("StaticFinalBuilder")
public static class Builder<BuilderType extends Builder> {
- private final Bundle mProperties = new Bundle();
- private final Bundle mBundle = new Bundle();
+ private final Bundle mBundle;
+ private final Bundle mProperties;
private final BuilderType mBuilderTypeInstance;
private boolean mBuilt = false;
@@ -964,6 +978,8 @@
Objects.requireNonNull(namespace);
Objects.requireNonNull(id);
Objects.requireNonNull(schemaType);
+
+ mBundle = new Bundle();
mBuilderTypeInstance = (BuilderType) this;
mBundle.putString(GenericDocument.NAMESPACE_FIELD, namespace);
mBundle.putString(GenericDocument.ID_FIELD, id);
@@ -973,9 +989,72 @@
GenericDocument.CREATION_TIMESTAMP_MILLIS_FIELD, System.currentTimeMillis());
mBundle.putLong(GenericDocument.TTL_MILLIS_FIELD, DEFAULT_TTL_MILLIS);
mBundle.putInt(GenericDocument.SCORE_FIELD, DEFAULT_SCORE);
+
+ mProperties = new Bundle();
mBundle.putBundle(PROPERTIES_FIELD, mProperties);
}
+ /** Creates a new {@link GenericDocument.Builder} from the given Bundle. */
+ @SuppressWarnings("unchecked")
+ Builder(@NonNull Bundle bundle) {
+ mBundle = Objects.requireNonNull(bundle);
+ mProperties = mBundle.getBundle(PROPERTIES_FIELD);
+ mBuilderTypeInstance = (BuilderType) this;
+ }
+
+ /**
+ * Sets the app-defined namespace this document resides in, changing the value provided in
+ * the constructor. No special values are reserved or understood by the infrastructure.
+ *
+ * <p>Document IDs are unique within a namespace.
+ *
+ * <p>The number of namespaces per app should be kept small for efficiency reasons.
+ *
+ * @throws IllegalStateException if the builder has already been used.
+ * @hide
+ */
+ @NonNull
+ public BuilderType setNamespace(@NonNull String namespace) {
+ Preconditions.checkState(!mBuilt, "Builder has already been used");
+ Objects.requireNonNull(namespace);
+ mBundle.putString(GenericDocument.NAMESPACE_FIELD, namespace);
+ return mBuilderTypeInstance;
+ }
+
+ /**
+ * Sets the ID of this document, changing the value provided in the constructor. No special
+ * values are reserved or understood by the infrastructure.
+ *
+ * <p>Document IDs are unique within a namespace.
+ *
+ * @throws IllegalStateException if the builder has already been used.
+ * @hide
+ */
+ @NonNull
+ public BuilderType setId(@NonNull String id) {
+ Preconditions.checkState(!mBuilt, "Builder has already been used");
+ Objects.requireNonNull(id);
+ mBundle.putString(GenericDocument.ID_FIELD, id);
+ return mBuilderTypeInstance;
+ }
+
+ /**
+ * Sets the schema type of this document, changing the value provided in the constructor.
+ *
+ * <p>To successfully index a document, the schema type must match the name of an {@link
+ * AppSearchSchema} object previously provided to {@link AppSearchSession#setSchema}.
+ *
+ * @throws IllegalStateException if the builder has already been used.
+ * @hide
+ */
+ @NonNull
+ public BuilderType setSchemaType(@NonNull String schemaType) {
+ Preconditions.checkState(!mBuilt, "Builder has already been used");
+ Objects.requireNonNull(schemaType);
+ mBundle.putString(GenericDocument.SCHEMA_TYPE_FIELD, schemaType);
+ return mBuilderTypeInstance;
+ }
+
/**
* Sets the score of the {@link GenericDocument}.
*
@@ -1156,6 +1235,22 @@
return mBuilderTypeInstance;
}
+ /**
+ * Clears the value for the property with the given name.
+ *
+ * <p>Note that this method does not support property paths.
+ *
+ * @param name The name of the property to clear.
+ * @hide
+ */
+ @NonNull
+ public BuilderType clearProperty(@NonNull String name) {
+ Preconditions.checkState(!mBuilt, "Builder has already been used");
+ Objects.requireNonNull(name);
+ mProperties.remove(name);
+ return mBuilderTypeInstance;
+ }
+
private void putInPropertyBundle(@NonNull String name, @NonNull String[] values)
throws IllegalArgumentException {
validateRepeatedPropertyLength(name, values.length);
diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/SearchResult.java b/apex/appsearch/framework/java/external/android/app/appsearch/SearchResult.java
index 4fc654f..b648071 100644
--- a/apex/appsearch/framework/java/external/android/app/appsearch/SearchResult.java
+++ b/apex/appsearch/framework/java/external/android/app/appsearch/SearchResult.java
@@ -34,7 +34,7 @@
* <ul>
* <li>The document which matched, using {@link #getGenericDocument}
* <li>Information about which properties in the document matched, and "snippet" information
- * containing textual summaries of the document's matches, using {@link #getMatches}
+ * containing textual summaries of the document's matches, using {@link #getMatchInfos}
* </ul>
*
* <p>"Snippet" refers to a substring of text from the content of document that is returned as a
@@ -44,7 +44,7 @@
*/
public final class SearchResult {
static final String DOCUMENT_FIELD = "document";
- static final String MATCHES_FIELD = "matches";
+ static final String MATCH_INFOS_FIELD = "matchInfos";
static final String PACKAGE_NAME_FIELD = "packageName";
static final String DATABASE_NAME_FIELD = "databaseName";
static final String RANKING_SIGNAL_FIELD = "rankingSignal";
@@ -55,7 +55,7 @@
@Nullable private GenericDocument mDocument;
/** Cache of the inflated matches. Comes from inflating mMatchBundles at first use. */
- @Nullable private List<MatchInfo> mMatches;
+ @Nullable private List<MatchInfo> mMatchInfos;
/** @hide */
public SearchResult(@NonNull Bundle bundle) {
@@ -82,8 +82,16 @@
return mDocument;
}
+ /** @deprecated This method exists only for dogfooder transition and must be removed. */
+ @Deprecated
+ @NonNull
+ public List<MatchInfo> getMatches() {
+ return getMatchInfos();
+ }
+
/**
- * Contains a list of Snippets that matched the request.
+ * Returns a list of {@link MatchInfo}s providing information about how the document in {@link
+ * #getGenericDocument} matched the query.
*
* @return List of matches based on {@link SearchSpec}. If snippeting is disabled using {@link
* SearchSpec.Builder#setSnippetCount} or {@link
@@ -91,17 +99,17 @@
* method returns an empty list.
*/
@NonNull
- public List<MatchInfo> getMatches() {
- if (mMatches == null) {
+ public List<MatchInfo> getMatchInfos() {
+ if (mMatchInfos == null) {
List<Bundle> matchBundles =
- Objects.requireNonNull(mBundle.getParcelableArrayList(MATCHES_FIELD));
- mMatches = new ArrayList<>(matchBundles.size());
+ Objects.requireNonNull(mBundle.getParcelableArrayList(MATCH_INFOS_FIELD));
+ mMatchInfos = new ArrayList<>(matchBundles.size());
for (int i = 0; i < matchBundles.size(); i++) {
MatchInfo matchInfo = new MatchInfo(matchBundles.get(i), getGenericDocument());
- mMatches.add(matchInfo);
+ mMatchInfos.add(matchInfo);
}
}
- return mMatches;
+ return mMatchInfos;
}
/**
@@ -184,9 +192,16 @@
return this;
}
- /** Adds another match to this SearchResult. */
+ /** @deprecated this method exists only for dogfooder transition and must be removed */
+ @Deprecated
@NonNull
public Builder addMatch(@NonNull MatchInfo matchInfo) {
+ return addMatchInfo(matchInfo);
+ }
+
+ /** Adds another match to this SearchResult. */
+ @NonNull
+ public Builder addMatchInfo(@NonNull MatchInfo matchInfo) {
Preconditions.checkState(!mBuilt, "Builder has already been used");
Preconditions.checkState(
matchInfo.mDocument == null,
@@ -212,7 +227,7 @@
@NonNull
public SearchResult build() {
Preconditions.checkState(!mBuilt, "Builder has already been used");
- mBundle.putParcelableArrayList(MATCHES_FIELD, mMatchInfos);
+ mBundle.putParcelableArrayList(MATCH_INFOS_FIELD, mMatchInfos);
mBuilt = true;
return new SearchResult(mBundle);
}
diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/SearchSpec.java b/apex/appsearch/framework/java/external/android/app/appsearch/SearchSpec.java
index 20e5b9d..1c57c75 100644
--- a/apex/appsearch/framework/java/external/android/app/appsearch/SearchSpec.java
+++ b/apex/appsearch/framework/java/external/android/app/appsearch/SearchSpec.java
@@ -323,6 +323,7 @@
mBundle = new Bundle();
mBundle.putInt(NUM_PER_PAGE_FIELD, DEFAULT_NUM_PER_PAGE);
mBundle.putInt(TERM_MATCH_TYPE_FIELD, TERM_MATCH_PREFIX);
+ mBundle.putInt(SNIPPET_COUNT_PER_PROPERTY_FIELD, MAX_SNIPPET_PER_PROPERTY_COUNT);
}
/**
@@ -471,8 +472,11 @@
* Only the first {@code snippetCount} documents based on the ranking strategy will have
* snippet information provided.
*
- * <p>If set to 0 (default), snippeting is disabled and {@link SearchResult#getMatches} will
- * return {@code null} for that result.
+ * <p>The list returned from {@link SearchResult#getMatchInfos} will contain at most this
+ * many entries.
+ *
+ * <p>If set to 0 (default), snippeting is disabled and the list returned from {@link
+ * SearchResult#getMatchInfos} will be empty.
*/
@NonNull
public SearchSpec.Builder setSnippetCount(
@@ -485,10 +489,14 @@
/**
* Sets {@code snippetCountPerProperty}. Only the first {@code snippetCountPerProperty}
- * snippets for each property of {@link GenericDocument} will contain snippet information.
+ * snippets for each property of each {@link GenericDocument} will contain snippet
+ * information.
*
- * <p>If set to 0, snippeting is disabled and {@link SearchResult#getMatches} will return
- * {@code null} for that result.
+ * <p>If set to 0, snippeting is disabled and the list returned from {@link
+ * SearchResult#getMatchInfos} will be empty.
+ *
+ * <p>The default behavior is to snippet all matches a property contains, up to the maximum
+ * value of 10,000.
*/
@NonNull
public SearchSpec.Builder setSnippetCountPerProperty(
diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/util/BundleUtil.java b/apex/appsearch/framework/java/external/android/app/appsearch/util/BundleUtil.java
index 14dd472..e77043f 100644
--- a/apex/appsearch/framework/java/external/android/app/appsearch/util/BundleUtil.java
+++ b/apex/appsearch/framework/java/external/android/app/appsearch/util/BundleUtil.java
@@ -16,8 +16,10 @@
package android.app.appsearch.util;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Bundle;
+import android.os.Parcel;
import android.util.SparseArray;
import java.util.ArrayList;
@@ -224,4 +226,26 @@
}
return Arrays.hashCode(hashCodes);
}
+
+ /**
+ * Deeply clones a Bundle.
+ *
+ * <p>Values which are Bundles, Lists or Arrays are deeply copied themselves.
+ */
+ @NonNull
+ public static Bundle deepCopy(@NonNull Bundle bundle) {
+ // Write bundle to bytes
+ Parcel parcel = Parcel.obtain();
+ try {
+ parcel.writeBundle(bundle);
+ byte[] serializedMessage = parcel.marshall();
+
+ // Read bundle from bytes
+ parcel.unmarshall(serializedMessage, 0, serializedMessage.length);
+ parcel.setDataPosition(0);
+ return parcel.readBundle();
+ } finally {
+ parcel.recycle();
+ }
+ }
}
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SearchResultToProtoConverter.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SearchResultToProtoConverter.java
index 84220d7..ecc774c 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SearchResultToProtoConverter.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SearchResultToProtoConverter.java
@@ -116,7 +116,7 @@
for (int j = 0; j < entry.getSnippetMatchesCount(); j++) {
SearchResult.MatchInfo matchInfo =
toMatchInfo(entry.getSnippetMatches(j), entry.getPropertyName());
- builder.addMatch(matchInfo);
+ builder.addMatchInfo(matchInfo);
}
}
}
diff --git a/apex/appsearch/synced_jetpack_changeid.txt b/apex/appsearch/synced_jetpack_changeid.txt
index 10bba13..277740f 100644
--- a/apex/appsearch/synced_jetpack_changeid.txt
+++ b/apex/appsearch/synced_jetpack_changeid.txt
@@ -1 +1 @@
-I19dac52031c47099f621eced9f148931f1021f25
+Ic6be29e84e7c6f31cdae37973850bb3395920326
diff --git a/apex/appsearch/testing/Android.bp b/apex/appsearch/testing/Android.bp
index 2518394..ec64941 100644
--- a/apex/appsearch/testing/Android.bp
+++ b/apex/appsearch/testing/Android.bp
@@ -31,6 +31,7 @@
"truth-prebuilt",
],
visibility: [
+ "//frameworks/base/core/tests/coretests",
"//cts/hostsidetests/appsearch",
"//cts/tests/appsearch",
"//vendor:__subpackages__",
diff --git a/apex/appsearch/testing/java/com/android/server/appsearch/testing/AppSearchSessionShimImpl.java b/apex/appsearch/testing/java/com/android/server/appsearch/testing/AppSearchSessionShimImpl.java
index 930cd60..941cea9 100644
--- a/apex/appsearch/testing/java/com/android/server/appsearch/testing/AppSearchSessionShimImpl.java
+++ b/apex/appsearch/testing/java/com/android/server/appsearch/testing/AppSearchSessionShimImpl.java
@@ -179,7 +179,7 @@
@Override
@NonNull
- public ListenableFuture<Void> maybeFlush() {
+ public ListenableFuture<Void> requestFlush() {
SettableFuture<AppSearchResult<Void>> future = SettableFuture.create();
// The data in platform will be flushed by scheduled task. AppSearchSession won't do
// anything extra flush.
diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/AppSearchEmail.java b/apex/appsearch/testing/java/com/android/server/appsearch/testing/external/AppSearchEmail.java
similarity index 92%
rename from apex/appsearch/framework/java/external/android/app/appsearch/AppSearchEmail.java
rename to apex/appsearch/testing/java/com/android/server/appsearch/testing/external/AppSearchEmail.java
index d99c73f..845274d 100644
--- a/apex/appsearch/framework/java/external/android/app/appsearch/AppSearchEmail.java
+++ b/apex/appsearch/testing/java/com/android/server/appsearch/testing/external/AppSearchEmail.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 The Android Open Source Project
+ * 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.
@@ -14,19 +14,19 @@
* limitations under the License.
*/
-package android.app.appsearch;
+package com.android.server.appsearch.testing;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.appsearch.AppSearchSchema;
import android.app.appsearch.AppSearchSchema.PropertyConfig;
import android.app.appsearch.AppSearchSchema.StringPropertyConfig;
+import android.app.appsearch.GenericDocument;
/**
* Encapsulates a {@link GenericDocument} that represent an email.
*
* <p>This class is a higher level implement of {@link GenericDocument}.
- *
- * @hide
*/
public class AppSearchEmail extends GenericDocument {
/** The name of the schema type for {@link AppSearchEmail} documents. */
@@ -151,9 +151,9 @@
}
/** The builder class for {@link AppSearchEmail}. */
- public static class Builder extends GenericDocument.Builder<AppSearchEmail.Builder> {
+ public static class Builder extends GenericDocument.Builder<Builder> {
/**
- * Creates a new {@link AppSearchEmail.Builder}
+ * Creates a new {@link Builder}
*
* @param namespace The namespace of the Email.
* @param id The ID of the Email.
@@ -164,42 +164,42 @@
/** Sets the from address of {@link AppSearchEmail} */
@NonNull
- public AppSearchEmail.Builder setFrom(@NonNull String from) {
+ public Builder setFrom(@NonNull String from) {
setPropertyString(KEY_FROM, from);
return this;
}
/** Sets the destination address of {@link AppSearchEmail} */
@NonNull
- public AppSearchEmail.Builder setTo(@NonNull String... to) {
+ public Builder setTo(@NonNull String... to) {
setPropertyString(KEY_TO, to);
return this;
}
/** Sets the CC list of {@link AppSearchEmail} */
@NonNull
- public AppSearchEmail.Builder setCc(@NonNull String... cc) {
+ public Builder setCc(@NonNull String... cc) {
setPropertyString(KEY_CC, cc);
return this;
}
/** Sets the BCC list of {@link AppSearchEmail} */
@NonNull
- public AppSearchEmail.Builder setBcc(@NonNull String... bcc) {
+ public Builder setBcc(@NonNull String... bcc) {
setPropertyString(KEY_BCC, bcc);
return this;
}
/** Sets the subject of {@link AppSearchEmail} */
@NonNull
- public AppSearchEmail.Builder setSubject(@NonNull String subject) {
+ public Builder setSubject(@NonNull String subject) {
setPropertyString(KEY_SUBJECT, subject);
return this;
}
/** Sets the body of {@link AppSearchEmail} */
@NonNull
- public AppSearchEmail.Builder setBody(@NonNull String body) {
+ public Builder setBody(@NonNull String body) {
setPropertyString(KEY_BODY, body);
return this;
}
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 345b059..a70d9b5 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
@@ -240,13 +240,16 @@
/**
* Flush all schema and document updates, additions, and deletes to disk if possible.
*
+ * <p>The request is not guaranteed to be handled and may be ignored by some implementations of
+ * AppSearchSessionShim.
+ *
* @return The pending result of performing this operation. {@link
* android.app.appsearch.exceptions.AppSearchException} with {@link
* AppSearchResult#RESULT_INTERNAL_ERROR} will be set to the future if we hit error when
* save to disk.
*/
@NonNull
- ListenableFuture<Void> maybeFlush();
+ ListenableFuture<Void> requestFlush();
/**
* Closes the {@link AppSearchSessionShim} to persist all schema and document updates,
diff --git a/apex/jobscheduler/framework/java/com/android/server/DeviceIdleInternal.java b/apex/jobscheduler/framework/java/com/android/server/DeviceIdleInternal.java
index a9ca5cf..caf7e7f 100644
--- a/apex/jobscheduler/framework/java/com/android/server/DeviceIdleInternal.java
+++ b/apex/jobscheduler/framework/java/com/android/server/DeviceIdleInternal.java
@@ -96,4 +96,13 @@
* that the device is stationary or in motion.
*/
void unregisterStationaryListener(StationaryListener listener);
+
+ /**
+ * Apply some restrictions on temp allowlist type based on the reasonCode.
+ * @param reasonCode temp allowlist reason code.
+ * @param defaultType default temp allowlist type if reasonCode can not decide a type.
+ * @return temp allowlist type based on the reasonCode.
+ */
+ @TempAllowListType int getTempAllowListType(@ReasonCode int reasonCode,
+ @TempAllowListType int defaultType);
}
diff --git a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
index 57c8300..60f5769 100644
--- a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
+++ b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
@@ -19,6 +19,7 @@
import static android.os.PowerExemptionManager.REASON_SHELL;
import static android.os.PowerExemptionManager.REASON_UNKNOWN;
import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
+import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_NONE;
import static android.os.Process.INVALID_UID;
import android.Manifest;
@@ -58,6 +59,7 @@
import android.os.IDeviceIdleController;
import android.os.Looper;
import android.os.Message;
+import android.os.PowerExemptionManager;
import android.os.PowerExemptionManager.ReasonCode;
import android.os.PowerExemptionManager.TempAllowListType;
import android.os.PowerManager;
@@ -2015,6 +2017,12 @@
public void unregisterStationaryListener(StationaryListener listener) {
DeviceIdleController.this.unregisterStationaryListener(listener);
}
+
+ @Override
+ public @TempAllowListType int getTempAllowListType(@ReasonCode int reasonCode,
+ @TempAllowListType int defaultType) {
+ return DeviceIdleController.this.getTempAllowListType(reasonCode, defaultType);
+ }
}
private class LocalPowerAllowlistService implements PowerAllowlistInternal {
@@ -2689,6 +2697,18 @@
}
}
+ private @TempAllowListType int getTempAllowListType(@ReasonCode int reasonCode,
+ @TempAllowListType int defaultType) {
+ switch (reasonCode) {
+ case PowerExemptionManager.REASON_PUSH_MESSAGING_OVER_QUOTA:
+ return mLocalActivityManager.getPushMessagingOverQuotaBehavior();
+ case PowerExemptionManager.REASON_DENIED:
+ return TEMPORARY_ALLOW_LIST_TYPE_NONE;
+ default:
+ return defaultType;
+ }
+ }
+
void addPowerSaveTempAllowlistAppChecked(String packageName, long duration,
int userId, @ReasonCode int reasonCode, @Nullable String reason)
throws RemoteException {
@@ -2705,9 +2725,12 @@
"addPowerSaveTempWhitelistApp", null);
final long token = Binder.clearCallingIdentity();
try {
- addPowerSaveTempAllowlistAppInternal(callingUid,
- packageName, duration, TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
- userId, true, reasonCode, reason);
+ @TempAllowListType int type = getTempAllowListType(reasonCode,
+ TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED);
+ if (type != TEMPORARY_ALLOW_LIST_TYPE_NONE) {
+ addPowerSaveTempAllowlistAppInternal(callingUid,
+ packageName, duration, type, userId, true, reasonCode, reason);
+ }
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -2741,16 +2764,6 @@
void addPowerSaveTempAllowlistAppInternal(int callingUid, String packageName,
long durationMs, @TempAllowListType int tempAllowListType, int userId, boolean sync,
@ReasonCode int reasonCode, @Nullable String reason) {
- synchronized (this) {
- int callingAppId = UserHandle.getAppId(callingUid);
- if (callingAppId >= Process.FIRST_APPLICATION_UID) {
- if (!mPowerSaveWhitelistSystemAppIds.get(callingAppId)) {
- throw new SecurityException(
- "Calling app " + UserHandle.formatUid(callingUid)
- + " is not on whitelist");
- }
- }
- }
try {
int uid = getContext().getPackageManager().getPackageUidAsUser(packageName, userId);
addPowerSaveTempWhitelistAppDirectInternal(callingUid, uid, durationMs,
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 54e47cf..0e36275 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
@@ -205,12 +205,11 @@
final LocalLog mLog = new LocalLog(TAG);
AppOpsManager mAppOps;
- IAppOpsService mAppOpsService;
DeviceIdleInternal mLocalDeviceIdleController;
private UsageStatsManagerInternal mUsageStatsManagerInternal;
private ActivityManagerInternal mActivityManagerInternal;
private PackageManagerInternal mPackageManagerInternal;
- private PermissionManagerServiceInternal mLocalPermissionManager;
+ private volatile PermissionManagerServiceInternal mLocalPermissionManager;
final Object mLock = new Object();
@@ -1506,7 +1505,7 @@
@Override
public void onStart() {
mInjector.init();
- mMetricsHelper = new MetricsHelper(getContext());
+ mMetricsHelper = new MetricsHelper(getContext(), mLock);
mListenerDeathRecipient = new IBinder.DeathRecipient() {
@Override
@@ -1630,40 +1629,14 @@
if (phase == PHASE_SYSTEM_SERVICES_READY) {
synchronized (mLock) {
mConstants.start();
+
mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
- mAppOpsService = mInjector.getAppOpsService();
- try {
- mAppOpsService.startWatchingMode(AppOpsManager.OP_SCHEDULE_EXACT_ALARM, null,
- new IAppOpsCallback.Stub() {
- @Override
- public void opChanged(int op, int uid, String packageName)
- throws RemoteException {
- if (op != AppOpsManager.OP_SCHEDULE_EXACT_ALARM) {
- return;
- }
- if (!hasScheduleExactAlarmInternal(packageName, uid)) {
- mHandler.obtainMessage(AlarmHandler.REMOVE_EXACT_ALARMS,
- uid, 0, packageName).sendToTarget();
- }
- }
- });
- } catch (RemoteException e) {
- }
- mMetricsHelper.registerPuller(mAlarmStore);
mLocalDeviceIdleController =
LocalServices.getService(DeviceIdleInternal.class);
mUsageStatsManagerInternal =
LocalServices.getService(UsageStatsManagerInternal.class);
- mLocalPermissionManager = LocalServices.getService(
- PermissionManagerServiceInternal.class);
- refreshExactAlarmCandidates();
-
- AppStandbyInternal appStandbyInternal =
- LocalServices.getService(AppStandbyInternal.class);
- appStandbyInternal.addListener(new AppStandbyTracker());
-
mAppStateTracker =
(AppStateTrackerImpl) LocalServices.getService(AppStateTracker.class);
mAppStateTracker.addListener(mForceAppStandbyListener);
@@ -1671,6 +1644,34 @@
mClockReceiver.scheduleTimeTickEvent();
mClockReceiver.scheduleDateChangedEvent();
}
+ IAppOpsService iAppOpsService = mInjector.getAppOpsService();
+ try {
+ iAppOpsService.startWatchingMode(AppOpsManager.OP_SCHEDULE_EXACT_ALARM, null,
+ new IAppOpsCallback.Stub() {
+ @Override
+ public void opChanged(int op, int uid, String packageName)
+ throws RemoteException {
+ if (op != AppOpsManager.OP_SCHEDULE_EXACT_ALARM) {
+ return;
+ }
+ if (!hasScheduleExactAlarmInternal(packageName, uid)) {
+ mHandler.obtainMessage(AlarmHandler.REMOVE_EXACT_ALARMS,
+ uid, 0, packageName).sendToTarget();
+ }
+ }
+ });
+ } catch (RemoteException e) {
+ }
+
+ mLocalPermissionManager = LocalServices.getService(
+ PermissionManagerServiceInternal.class);
+ refreshExactAlarmCandidates();
+
+ AppStandbyInternal appStandbyInternal =
+ LocalServices.getService(AppStandbyInternal.class);
+ appStandbyInternal.addListener(new AppStandbyTracker());
+
+ mMetricsHelper.registerPuller(() -> mAlarmStore);
}
}
diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/MetricsHelper.java b/apex/jobscheduler/service/java/com/android/server/alarm/MetricsHelper.java
index a8cf7b2..2dc131c 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/MetricsHelper.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/MetricsHelper.java
@@ -30,17 +30,21 @@
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.FrameworkStatsLog;
+import java.util.function.Supplier;
+
/**
* A helper class to write logs to statsd.
*/
class MetricsHelper {
- private Context mContext;
+ private final Context mContext;
+ private final Object mLock;
- MetricsHelper(Context context) {
+ MetricsHelper(Context context, Object lock) {
mContext = context;
+ mLock = lock;
}
- void registerPuller(AlarmStore alarmStore) {
+ void registerPuller(Supplier<AlarmStore> alarmStoreSupplier) {
final StatsManager statsManager = mContext.getSystemService(StatsManager.class);
statsManager.setPullAtomCallback(FrameworkStatsLog.PENDING_ALARM_INFO, null,
BackgroundThread.getExecutor(), (atomTag, data) -> {
@@ -48,26 +52,30 @@
throw new UnsupportedOperationException("Unknown tag" + atomTag);
}
final long now = SystemClock.elapsedRealtime();
- data.add(FrameworkStatsLog.buildStatsEvent(atomTag,
- alarmStore.size(),
- alarmStore.getCount(a -> a.windowLength == 0),
- alarmStore.getCount(a -> a.wakeup),
- alarmStore.getCount(
- a -> (a.flags & AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0),
- alarmStore.getCount(a -> (a.flags & AlarmManager.FLAG_PRIORITIZE) != 0),
- alarmStore.getCount(a -> (a.operation != null
- && a.operation.isForegroundService())),
- alarmStore.getCount(
- a -> (a.operation != null && a.operation.isActivity())),
- alarmStore.getCount(
- a -> (a.operation != null && a.operation.isService())),
- alarmStore.getCount(a -> (a.listener != null)),
- alarmStore.getCount(
- a -> (a.getRequestedElapsed() > now + INDEFINITE_DELAY)),
- alarmStore.getCount(a -> (a.repeatInterval != 0)),
- alarmStore.getCount(a -> (a.alarmClock != null))
- ));
- return StatsManager.PULL_SUCCESS;
+ synchronized (mLock) {
+ final AlarmStore alarmStore = alarmStoreSupplier.get();
+ data.add(FrameworkStatsLog.buildStatsEvent(atomTag,
+ alarmStore.size(),
+ alarmStore.getCount(a -> a.windowLength == 0),
+ alarmStore.getCount(a -> a.wakeup),
+ alarmStore.getCount(
+ a -> (a.flags & AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0),
+ alarmStore.getCount(
+ a -> (a.flags & AlarmManager.FLAG_PRIORITIZE) != 0),
+ alarmStore.getCount(a -> (a.operation != null
+ && a.operation.isForegroundService())),
+ alarmStore.getCount(
+ a -> (a.operation != null && a.operation.isActivity())),
+ alarmStore.getCount(
+ a -> (a.operation != null && a.operation.isService())),
+ alarmStore.getCount(a -> (a.listener != null)),
+ alarmStore.getCount(
+ a -> (a.getRequestedElapsed() > now + INDEFINITE_DELAY)),
+ alarmStore.getCount(a -> (a.repeatInterval != 0)),
+ alarmStore.getCount(a -> (a.alarmClock != null))
+ ));
+ return StatsManager.PULL_SUCCESS;
+ }
});
}
diff --git a/cmds/sm/src/com/android/commands/sm/Sm.java b/cmds/sm/src/com/android/commands/sm/Sm.java
index 260c8a4..f5bee6c 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, false)) {
+ ANDROID_VOLD_APP_DATA_ISOLATION_ENABLED_PROPERTY, true)) {
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 2bada80..a372033 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -7466,9 +7466,10 @@
field public static final int LOCK_TASK_FEATURE_SYSTEM_INFO = 1; // 0x1
field public static final int MAKE_USER_EPHEMERAL = 2; // 0x2
field public static final String MIME_TYPE_PROVISIONING_NFC = "application/com.android.managedprovisioning";
- field public static final int NEARBY_STREAMING_DISABLED = 0; // 0x0
- field public static final int NEARBY_STREAMING_ENABLED = 1; // 0x1
- field public static final int NEARBY_STREAMING_SAME_MANAGED_ACCOUNT_ONLY = 2; // 0x2
+ field public static final int NEARBY_STREAMING_DISABLED = 1; // 0x1
+ field public static final int NEARBY_STREAMING_ENABLED = 2; // 0x2
+ field public static final int NEARBY_STREAMING_NOT_CONTROLLED_BY_POLICY = 0; // 0x0
+ field public static final int NEARBY_STREAMING_SAME_MANAGED_ACCOUNT_ONLY = 3; // 0x3
field public static final int OPERATION_SAFETY_REASON_DRIVING_DISTRACTION = 1; // 0x1
field public static final int PASSWORD_COMPLEXITY_HIGH = 327680; // 0x50000
field public static final int PASSWORD_COMPLEXITY_LOW = 65536; // 0x10000
@@ -9035,7 +9036,7 @@
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_PRIVILEGED) public boolean setPairingConfirmation(boolean);
+ 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);
field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_ACL_CONNECTED = "android.bluetooth.device.action.ACL_CONNECTED";
@@ -17136,11 +17137,11 @@
package android.hardware {
- public abstract class Battery {
- ctor public Battery();
+ public abstract class BatteryState {
+ ctor public BatteryState();
method @FloatRange(from=-1.0F, to=1.0f) public abstract float getCapacity();
method public abstract int getStatus();
- method public abstract boolean hasBattery();
+ method public abstract boolean isPresent();
field public static final int STATUS_CHARGING = 2; // 0x2
field public static final int STATUS_DISCHARGING = 3; // 0x3
field public static final int STATUS_FULL = 5; // 0x5
@@ -18991,7 +18992,6 @@
}
public abstract static class LightsManager.LightsSession implements java.lang.AutoCloseable {
- ctor public LightsManager.LightsSession();
method public abstract void close();
method public abstract void requestLights(@NonNull android.hardware.lights.LightsRequest);
}
@@ -47130,7 +47130,7 @@
public final class InputDevice implements android.os.Parcelable {
method public int describeContents();
- method @NonNull public android.hardware.Battery getBattery();
+ method @NonNull public android.hardware.BatteryState getBatteryState();
method public int getControllerNumber();
method public String getDescriptor();
method public static android.view.InputDevice getDevice(int);
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 3537d8b..99a7998 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -1930,16 +1930,16 @@
}
public final class BluetoothAdapter {
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean addOnMetadataChangedListener(@NonNull android.bluetooth.BluetoothDevice, @NonNull java.util.concurrent.Executor, @NonNull android.bluetooth.BluetoothAdapter.OnMetadataChangedListener);
+ method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean addOnMetadataChangedListener(@NonNull android.bluetooth.BluetoothDevice, @NonNull java.util.concurrent.Executor, @NonNull android.bluetooth.BluetoothAdapter.OnMetadataChangedListener);
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean disableBLE();
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean enableBLE();
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean enableNoAutoConnect();
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public void generateLocalOobData(int, @NonNull java.util.concurrent.Executor, @NonNull android.bluetooth.BluetoothAdapter.OobDataCallback);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public long getDiscoveryEndMillis();
+ method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public void generateLocalOobData(int, @NonNull java.util.concurrent.Executor, @NonNull android.bluetooth.BluetoothAdapter.OobDataCallback);
+ method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public long getDiscoveryEndMillis();
method public boolean isBleScanAlwaysAvailable();
method public boolean isLeEnabled();
method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean removeActiveDevice(int);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean removeOnMetadataChangedListener(@NonNull android.bluetooth.BluetoothDevice, @NonNull android.bluetooth.BluetoothAdapter.OnMetadataChangedListener);
+ method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean removeOnMetadataChangedListener(@NonNull android.bluetooth.BluetoothDevice, @NonNull android.bluetooth.BluetoothAdapter.OnMetadataChangedListener);
method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean setActiveDevice(@NonNull android.bluetooth.BluetoothDevice, int);
field public static final String ACTION_BLE_STATE_CHANGED = "android.bluetooth.adapter.action.BLE_STATE_CHANGED";
field public static final String ACTION_REQUEST_BLE_SCAN_ALWAYS_AVAILABLE = "android.bluetooth.adapter.action.REQUEST_BLE_SCAN_ALWAYS_AVAILABLE";
@@ -1957,24 +1957,24 @@
public static interface BluetoothAdapter.OobDataCallback {
method public void onError(int);
- method public void onOobData(int, @Nullable android.bluetooth.OobData);
+ method public void onOobData(int, @NonNull android.bluetooth.OobData);
}
public final class BluetoothDevice implements android.os.Parcelable {
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean canBondWithoutDialog();
+ method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean canBondWithoutDialog();
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean cancelBondProcess();
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean createBondOutOfBand(int, @Nullable android.bluetooth.OobData, @Nullable android.bluetooth.OobData);
- method @Nullable @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public byte[] getMetadata(int);
+ method @Nullable @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public byte[] getMetadata(int);
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getSimAccessPermission();
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean isConnected();
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean isEncrypted();
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean isInSilenceMode();
+ method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean isInSilenceMode();
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean removeBond();
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean setMessageAccessPermission(int);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean setMetadata(int, @NonNull byte[]);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean setPhonebookAccessPermission(int);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean setSilenceMode(boolean);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean setSimAccessPermission(int);
+ method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setMessageAccessPermission(int);
+ method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setMetadata(int, @NonNull byte[]);
+ method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setPhonebookAccessPermission(int);
+ method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setSilenceMode(boolean);
+ method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setSimAccessPermission(int);
field public static final int ACCESS_ALLOWED = 1; // 0x1
field public static final int ACCESS_REJECTED = 2; // 0x2
field public static final int ACCESS_UNKNOWN = 0; // 0x0
@@ -2140,8 +2140,6 @@
}
public final class OobData implements android.os.Parcelable {
- method @NonNull public static android.bluetooth.OobData.ClassicBuilder createClassicBuilder(@NonNull byte[], @NonNull byte[], @NonNull byte[]);
- method @NonNull public static android.bluetooth.OobData.LeBuilder createLeBuilder(@NonNull byte[], @NonNull byte[], int);
method @NonNull public byte[] getClassOfDevice();
method @NonNull public byte[] getClassicLength();
method @NonNull public byte[] getConfirmationHash();
@@ -2174,6 +2172,7 @@
}
public static final class OobData.ClassicBuilder {
+ ctor public OobData.ClassicBuilder(@NonNull byte[], @NonNull byte[], @NonNull byte[]);
method @NonNull public android.bluetooth.OobData build();
method @NonNull public android.bluetooth.OobData.ClassicBuilder setClassOfDevice(@NonNull byte[]);
method @NonNull public android.bluetooth.OobData.ClassicBuilder setDeviceName(@NonNull byte[]);
@@ -2181,6 +2180,7 @@
}
public static final class OobData.LeBuilder {
+ ctor public OobData.LeBuilder(@NonNull byte[], @NonNull byte[], int);
method @NonNull public android.bluetooth.OobData build();
method @NonNull public android.bluetooth.OobData.LeBuilder setDeviceName(@NonNull byte[]);
method @NonNull public android.bluetooth.OobData.LeBuilder setLeFlags(int);
@@ -2757,6 +2757,7 @@
field public static final int FLAG_PERMISSION_REVIEW_REQUIRED = 64; // 0x40
field public static final int FLAG_PERMISSION_REVOKED_COMPAT = 8; // 0x8
field @Deprecated public static final int FLAG_PERMISSION_REVOKE_ON_UPGRADE = 8; // 0x8
+ field public static final int FLAG_PERMISSION_REVOKE_WHEN_REQUESTED = 128; // 0x80
field public static final int FLAG_PERMISSION_SELECTED_LOCATION_ACCURACY = 524288; // 0x80000
field public static final int FLAG_PERMISSION_SYSTEM_FIXED = 16; // 0x10
field public static final int FLAG_PERMISSION_USER_FIXED = 2; // 0x2
@@ -10782,10 +10783,6 @@
method public final void addExistingConnection(@NonNull android.telecom.PhoneAccountHandle, @NonNull android.telecom.Connection, @NonNull android.telecom.Conference);
}
- @Deprecated public abstract class DiagnosticCall extends android.telecom.CallDiagnostics {
- ctor @Deprecated public DiagnosticCall();
- }
-
public abstract class InCallService extends android.app.Service {
method @Deprecated public android.telecom.Phone getPhone();
method @Deprecated public void onPhoneCreated(android.telecom.Phone);
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index dd97cda1..61a9954 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -2674,6 +2674,12 @@
public final class ContentInfo {
method @NonNull public android.util.Pair<android.view.ContentInfo,android.view.ContentInfo> partition(@NonNull java.util.function.Predicate<android.content.ClipData.Item>);
+ method public void releasePermissions();
+ }
+
+ public static final class ContentInfo.Builder {
+ method @NonNull public android.view.ContentInfo.Builder setDragAndDropPermissions(@Nullable android.view.DragAndDropPermissions);
+ method @NonNull public android.view.ContentInfo.Builder setInputContentInfo(@Nullable android.view.inputmethod.InputContentInfo);
}
public final class Display {
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 6053400..ab610e4 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -583,4 +583,9 @@
* Is the FGS started from an uid temporarily allowed to have while-in-use permission?
*/
public abstract boolean isTempAllowlistedForFgsWhileInUse(int uid);
+
+ /**
+ * Return the temp allowlist type when server push messaging is over the quota.
+ */
+ public abstract @TempAllowListType int getPushMessagingOverQuotaBehavior();
}
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index d798620..d77ce4a 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -1237,9 +1237,17 @@
public static final int OP_ACTIVITY_RECOGNITION_SOURCE =
AppProtoEnums.APP_OP_ACTIVITY_RECOGNITION_SOURCE;
+ /**
+ * Incoming phone audio is being recorded
+ *
+ * @hide
+ */
+ public static final int OP_RECORD_INCOMING_PHONE_AUDIO =
+ AppProtoEnums.APP_OP_RECORD_INCOMING_PHONE_AUDIO;
+
/** @hide */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public static final int _NUM_OP = 115;
+ public static final int _NUM_OP = 116;
/** Access to coarse location information. */
public static final String OPSTR_COARSE_LOCATION = "android:coarse_location";
@@ -1669,6 +1677,12 @@
public static final String OPSTR_ACTIVITY_RECOGNITION_SOURCE =
"android:activity_recognition_source";
+ /**
+ * @hide
+ */
+ public static final String OPSTR_RECORD_INCOMING_PHONE_AUDIO =
+ "android:record_incoming_phone_audio";
+
/** {@link #sAppOpsToNote} not initialized yet for this op */
private static final byte SHOULD_COLLECT_NOTE_OP_NOT_INITIALIZED = 0;
/** Should not collect noting of this app-op in {@link #sAppOpsToNote} */
@@ -1882,6 +1896,7 @@
OP_UWB_RANGING, // OP_UWB_RANGING
OP_ACTIVITY_RECOGNITION_SOURCE, // OP_ACTIVITY_RECOGNITION_SOURCE
OP_BLUETOOTH_ADVERTISE, // OP_BLUETOOTH_ADVERTISE
+ OP_RECORD_INCOMING_PHONE_AUDIO, // OP_RECORD_INCOMING_PHONE_AUDIO
};
/**
@@ -2003,6 +2018,7 @@
OPSTR_UWB_RANGING,
OPSTR_ACTIVITY_RECOGNITION_SOURCE,
OPSTR_BLUETOOTH_ADVERTISE,
+ OPSTR_RECORD_INCOMING_PHONE_AUDIO,
};
/**
@@ -2125,6 +2141,7 @@
"UWB_RANGING",
"ACTIVITY_RECOGNITION_SOURCE",
"BLUETOOTH_ADVERTISE",
+ "RECORD_INCOMING_PHONE_AUDIO",
};
/**
@@ -2248,6 +2265,7 @@
Manifest.permission.UWB_RANGING,
null, // no permission for OP_ACTIVITY_RECOGNITION_SOURCE,
Manifest.permission.BLUETOOTH_ADVERTISE,
+ null, // no permission for OP_RECORD_INCOMING_PHONE_AUDIO,
};
/**
@@ -2371,6 +2389,7 @@
null, // UWB_RANGING
null, // ACTIVITY_RECOGNITION_SOURCE
null, // BLUETOOTH_ADVERTISE
+ null, // RECORD_INCOMING_PHONE_AUDIO
};
/**
@@ -2493,6 +2512,7 @@
null, // UWB_RANGING
null, // ACTIVITY_RECOGNITION_SOURCE
null, // BLUETOOTH_ADVERTISE
+ null, // RECORD_INCOMING_PHONE_AUDIO
};
/**
@@ -2614,6 +2634,7 @@
AppOpsManager.MODE_ALLOWED, // UWB_RANGING
AppOpsManager.MODE_ALLOWED, // ACTIVITY_RECOGNITION_SOURCE
AppOpsManager.MODE_ALLOWED, // BLUETOOTH_ADVERTISE
+ AppOpsManager.MODE_ALLOWED, // RECORD_INCOMING_PHONE_AUDIO
};
/**
@@ -2739,6 +2760,7 @@
false, // UWB_RANGING
false, // ACTIVITY_RECOGNITION_SOURCE
false, // BLUETOOTH_ADVERTISE
+ false, // RECORD_INCOMING_PHONE_AUDIO
};
/**
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index cbf2d6a..f07f453 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -1678,23 +1678,30 @@
})
public @interface PasswordComplexity {}
+ /**
+ * Indicates that nearby streaming is not controlled by policy, which means nearby streaming is
+ * allowed.
+ */
+ public static final int NEARBY_STREAMING_NOT_CONTROLLED_BY_POLICY = 0;
+
/** Indicates that nearby streaming is disabled. */
- public static final int NEARBY_STREAMING_DISABLED = 0;
+ public static final int NEARBY_STREAMING_DISABLED = 1;
/** Indicates that nearby streaming is enabled. */
- public static final int NEARBY_STREAMING_ENABLED = 1;
+ public static final int NEARBY_STREAMING_ENABLED = 2;
/**
* Indicates that nearby streaming is enabled only to devices offering a comparable level of
* security, with the same authenticated managed account.
*/
- public static final int NEARBY_STREAMING_SAME_MANAGED_ACCOUNT_ONLY = 2;
+ public static final int NEARBY_STREAMING_SAME_MANAGED_ACCOUNT_ONLY = 3;
/**
* @hide
*/
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = {"NEARBY_STREAMING_"}, value = {
+ NEARBY_STREAMING_NOT_CONTROLLED_BY_POLICY,
NEARBY_STREAMING_DISABLED,
NEARBY_STREAMING_ENABLED,
NEARBY_STREAMING_SAME_MANAGED_ACCOUNT_ONLY,
@@ -7199,15 +7206,20 @@
/**
* Returns the current runtime nearby notification streaming policy set by the device or profile
- * owner. The default is {@link #NEARBY_STREAMING_DISABLED}.
+ * owner.
*/
public @NearbyStreamingPolicy int getNearbyNotificationStreamingPolicy() {
+ return getNearbyNotificationStreamingPolicy(myUserId());
+ }
+
+ /** @hide per-user version */
+ public @NearbyStreamingPolicy int getNearbyNotificationStreamingPolicy(int userId) {
throwIfParentInstance("getNearbyNotificationStreamingPolicy");
if (mService == null) {
- return NEARBY_STREAMING_DISABLED;
+ return NEARBY_STREAMING_NOT_CONTROLLED_BY_POLICY;
}
try {
- return mService.getNearbyNotificationStreamingPolicy();
+ return mService.getNearbyNotificationStreamingPolicy(userId);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
@@ -7235,15 +7247,19 @@
/**
* Returns the current runtime nearby app streaming policy set by the device or profile owner.
- * The default is {@link #NEARBY_STREAMING_DISABLED}.
*/
public @NearbyStreamingPolicy int getNearbyAppStreamingPolicy() {
+ return getNearbyAppStreamingPolicy(myUserId());
+ }
+
+ /** @hide per-user version */
+ public @NearbyStreamingPolicy int getNearbyAppStreamingPolicy(int userId) {
throwIfParentInstance("getNearbyAppStreamingPolicy");
if (mService == null) {
- return NEARBY_STREAMING_DISABLED;
+ return NEARBY_STREAMING_NOT_CONTROLLED_BY_POLICY;
}
try {
- return mService.getNearbyAppStreamingPolicy();
+ return mService.getNearbyAppStreamingPolicy(userId);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 8e86f65..370db60 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -134,10 +134,10 @@
boolean getScreenCaptureDisabled(in ComponentName who, int userHandle, boolean parent);
void setNearbyNotificationStreamingPolicy(int policy);
- int getNearbyNotificationStreamingPolicy();
+ int getNearbyNotificationStreamingPolicy(int userId);
void setNearbyAppStreamingPolicy(int policy);
- int getNearbyAppStreamingPolicy();
+ int getNearbyAppStreamingPolicy(int userId);
void setKeyguardDisabledFeatures(in ComponentName who, int which, boolean parent);
int getKeyguardDisabledFeatures(in ComponentName who, int userHandle, boolean parent);
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 8afc557..9fc1f88 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -1311,11 +1311,15 @@
* @hide
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+ })
public boolean factoryReset() {
try {
mServiceLock.readLock().lock();
- if (mService != null && mService.factoryReset()
+ if (mService != null && mService.factoryReset(mAttributionSource)
&& mManagerService != null
&& mManagerService.onFactoryReset(mAttributionSource)) {
return true;
@@ -1430,7 +1434,11 @@
*
* @hide
*/
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+ })
public boolean setBluetoothClass(BluetoothClass bluetoothClass) {
if (getState() != STATE_ON) {
return false;
@@ -1438,7 +1446,7 @@
try {
mServiceLock.readLock().lock();
if (mService != null) {
- return mService.setBluetoothClass(bluetoothClass);
+ return mService.setBluetoothClass(bluetoothClass, mAttributionSource);
}
} catch (RemoteException e) {
Log.e(TAG, "", e);
@@ -1487,12 +1495,16 @@
*
* @hide
*/
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+ })
public boolean setIoCapability(@IoCapability int capability) {
if (getState() != STATE_ON) return false;
try {
mServiceLock.readLock().lock();
- if (mService != null) return mService.setIoCapability(capability);
+ if (mService != null) return mService.setIoCapability(capability, mAttributionSource);
} catch (RemoteException e) {
Log.e(TAG, e.getMessage(), e);
} finally {
@@ -1540,12 +1552,16 @@
*
* @hide
*/
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+ })
public boolean setLeIoCapability(@IoCapability int capability) {
if (getState() != STATE_ON) return false;
try {
mServiceLock.readLock().lock();
- if (mService != null) return mService.setLeIoCapability(capability);
+ if (mService != null) return mService.setLeIoCapability(capability, mAttributionSource);
} catch (RemoteException e) {
Log.e(TAG, e.getMessage(), e);
} finally {
@@ -1739,12 +1755,16 @@
* @hide
*/
@SystemApi
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+ })
public long getDiscoveryEndMillis() {
try {
mServiceLock.readLock().lock();
if (mService != null) {
- return mService.getDiscoveryEndMillis();
+ return mService.getDiscoveryEndMillis(mAttributionSource);
}
} catch (RemoteException e) {
Log.e(TAG, "", e);
@@ -2353,7 +2373,11 @@
* instead.
*/
@Deprecated
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+ })
public BluetoothActivityEnergyInfo getControllerActivityEnergyInfo(int updateType) {
SynchronousResultReceiver receiver = new SynchronousResultReceiver();
requestControllerActivityEnergyInfo(receiver);
@@ -2379,12 +2403,16 @@
* @param result The callback to which to send the activity info.
* @hide
*/
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+ })
public void requestControllerActivityEnergyInfo(ResultReceiver result) {
try {
mServiceLock.readLock().lock();
if (mService != null) {
- mService.requestActivityInfo(result);
+ mService.requestActivityInfo(result, mAttributionSource);
result = null;
}
} catch (RemoteException e) {
@@ -3141,7 +3169,7 @@
sMetadataListeners.forEach((device, pair) -> {
try {
mService.registerMetadataListener(sBluetoothMetadataListener,
- device);
+ device, mAttributionSource);
} catch (RemoteException e) {
Log.e(TAG, "Failed to register metadata listener", e);
}
@@ -3150,7 +3178,8 @@
synchronized (mBluetoothConnectionCallbackExecutorMap) {
if (!mBluetoothConnectionCallbackExecutorMap.isEmpty()) {
try {
- mService.registerBluetoothConnectionCallback(mConnectionCallback);
+ mService.registerBluetoothConnectionCallback(mConnectionCallback,
+ mAttributionSource);
} catch (RemoteException e) {
Log.e(TAG, "onBluetoothServiceUp: Failed to register bluetooth"
+ "connection callback", e);
@@ -3276,7 +3305,7 @@
* @param transport - whether the {@link OobData} is generated for LE or Classic.
* @param oobData - data generated in the host stack(LE) or controller (Classic)
*/
- void onOobData(@Transport int transport, @Nullable OobData oobData);
+ void onOobData(@Transport int transport, @NonNull OobData oobData);
/**
* Provides feedback when things don't go as expected.
@@ -3317,7 +3346,7 @@
*
* @hide
*/
- public void onOobData(@Transport int transport, OobData oobData) {
+ public void onOobData(@Transport int transport, @NonNull OobData oobData) {
mExecutor.execute(new Runnable() {
public void run() {
mCallback.onOobData(transport, oobData);
@@ -3364,7 +3393,11 @@
* @hide
*/
@SystemApi
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+ })
public void generateLocalOobData(@Transport int transport,
@NonNull @CallbackExecutor Executor executor, @NonNull OobDataCallback callback) {
if (transport != BluetoothDevice.TRANSPORT_BREDR && transport
@@ -3378,7 +3411,7 @@
} else {
try {
mService.generateLocalOobData(transport, new WrappedOobDataCallback(callback,
- executor));
+ executor), mAttributionSource);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
@@ -3515,11 +3548,13 @@
/** {@hide} */
@UnsupportedAppUsage
+ @RequiresNoPermission
public IBluetoothManager getBluetoothManager() {
return mManagerService;
}
/** {@hide} */
+ @RequiresNoPermission
public AttributionSource getAttributionSource() {
return mAttributionSource;
}
@@ -3892,7 +3927,11 @@
* @hide
*/
@SystemApi
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+ })
public boolean addOnMetadataChangedListener(@NonNull BluetoothDevice device,
@NonNull Executor executor, @NonNull OnMetadataChangedListener listener) {
if (DBG) Log.d(TAG, "addOnMetadataChangedListener()");
@@ -3932,7 +3971,8 @@
boolean ret = false;
try {
- ret = service.registerMetadataListener(sBluetoothMetadataListener, device);
+ ret = service.registerMetadataListener(sBluetoothMetadataListener, device,
+ mAttributionSource);
} catch (RemoteException e) {
Log.e(TAG, "registerMetadataListener fail", e);
} finally {
@@ -3965,7 +4005,11 @@
* @hide
*/
@SystemApi
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+ })
public boolean removeOnMetadataChangedListener(@NonNull BluetoothDevice device,
@NonNull OnMetadataChangedListener listener) {
if (DBG) Log.d(TAG, "removeOnMetadataChangedListener()");
@@ -3993,7 +4037,7 @@
return true;
}
try {
- return service.unregisterMetadataListener(device);
+ return service.unregisterMetadataListener(device, mAttributionSource);
} catch (RemoteException e) {
Log.e(TAG, "unregisterMetadataListener fail", e);
return false;
@@ -4055,7 +4099,11 @@
* @throws IllegalArgumentException if the callback is already registered
* @hide
*/
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+ })
public boolean registerBluetoothConnectionCallback(@NonNull @CallbackExecutor Executor executor,
@NonNull BluetoothConnectionCallback callback) {
if (DBG) Log.d(TAG, "registerBluetoothConnectionCallback()");
@@ -4069,7 +4117,8 @@
try {
mServiceLock.readLock().lock();
if (mService != null) {
- if (!mService.registerBluetoothConnectionCallback(mConnectionCallback)) {
+ if (!mService.registerBluetoothConnectionCallback(mConnectionCallback,
+ mAttributionSource)) {
return false;
}
}
@@ -4098,7 +4147,11 @@
* @return true if the callback was unregistered successfully, false otherwise
* @hide
*/
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+ })
public boolean unregisterBluetoothConnectionCallback(
@NonNull BluetoothConnectionCallback callback) {
if (DBG) Log.d(TAG, "unregisterBluetoothConnectionCallback()");
@@ -4120,7 +4173,8 @@
try {
mServiceLock.readLock().lock();
if (mService != null) {
- return mService.unregisterBluetoothConnectionCallback(mConnectionCallback);
+ return mService.unregisterBluetoothConnectionCallback(mConnectionCallback,
+ mAttributionSource);
}
} catch (RemoteException e) {
Log.e(TAG, "", e);
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index 98823b09..0ca6d74 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -1644,7 +1644,10 @@
* @hide
*/
@SystemApi
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+ })
public boolean canBondWithoutDialog() {
final IBluetooth service = sService;
if (service == null) {
@@ -1653,7 +1656,7 @@
}
try {
if (DBG) Log.d(TAG, "canBondWithoutDialog, device: " + this);
- return service.canBondWithoutDialog(this);
+ return service.canBondWithoutDialog(this, mAttributionSource);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
@@ -1874,7 +1877,10 @@
*
* @return true confirmation has been sent out false for error
*/
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+ })
public boolean setPairingConfirmation(boolean confirm) {
final IBluetooth service = sService;
if (service == null) {
@@ -1882,7 +1888,7 @@
return false;
}
try {
- return service.setPairingConfirmation(this, confirm);
+ return service.setPairingConfirmation(this, confirm, mAttributionSource);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
@@ -1971,14 +1977,17 @@
* @hide
*/
@SystemApi
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+ })
public boolean setSilenceMode(boolean silence) {
final IBluetooth service = sService;
if (service == null) {
throw new IllegalStateException("Bluetooth is not turned ON");
}
try {
- return service.setSilenceMode(this, silence);
+ return service.setSilenceMode(this, silence, mAttributionSource);
} catch (RemoteException e) {
Log.e(TAG, "setSilenceMode fail", e);
return false;
@@ -1993,14 +2002,17 @@
* @hide
*/
@SystemApi
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+ })
public boolean isInSilenceMode() {
final IBluetooth service = sService;
if (service == null) {
throw new IllegalStateException("Bluetooth is not turned ON");
}
try {
- return service.getSilenceMode(this);
+ return service.getSilenceMode(this, mAttributionSource);
} catch (RemoteException e) {
Log.e(TAG, "isInSilenceMode fail", e);
return false;
@@ -2016,14 +2028,17 @@
* @hide
*/
@SystemApi
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+ })
public boolean setPhonebookAccessPermission(@AccessPermission int value) {
final IBluetooth service = sService;
if (service == null) {
return false;
}
try {
- return service.setPhonebookAccessPermission(this, value);
+ return service.setPhonebookAccessPermission(this, value, mAttributionSource);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
@@ -2063,7 +2078,10 @@
* @hide
*/
@SystemApi
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+ })
public boolean setMessageAccessPermission(@AccessPermission int value) {
// Validates param value is one of the accepted constants
if (value != ACCESS_ALLOWED && value != ACCESS_REJECTED && value != ACCESS_UNKNOWN) {
@@ -2074,7 +2092,7 @@
return false;
}
try {
- return service.setMessageAccessPermission(this, value);
+ return service.setMessageAccessPermission(this, value, mAttributionSource);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
@@ -2114,14 +2132,17 @@
* @hide
*/
@SystemApi
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+ })
public boolean setSimAccessPermission(int value) {
final IBluetooth service = sService;
if (service == null) {
return false;
}
try {
- return service.setSimAccessPermission(this, value);
+ return service.setSimAccessPermission(this, value, mAttributionSource);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
@@ -2616,7 +2637,10 @@
* @hide
*/
@SystemApi
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+ })
public boolean setMetadata(@MetadataKey int key, @NonNull byte[] value) {
final IBluetooth service = sService;
if (service == null) {
@@ -2628,7 +2652,7 @@
+ ", should not over " + METADATA_MAX_LENGTH);
}
try {
- return service.setMetadata(this, key, value);
+ return service.setMetadata(this, key, value, mAttributionSource);
} catch (RemoteException e) {
Log.e(TAG, "setMetadata fail", e);
return false;
@@ -2644,7 +2668,10 @@
*/
@SystemApi
@Nullable
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+ })
public byte[] getMetadata(@MetadataKey int key) {
final IBluetooth service = sService;
if (service == null) {
@@ -2652,7 +2679,7 @@
return null;
}
try {
- return service.getMetadata(this, key);
+ return service.getMetadata(this, key, mAttributionSource);
} catch (RemoteException e) {
Log.e(TAG, "getMetadata fail", e);
return null;
diff --git a/core/java/android/bluetooth/OobData.java b/core/java/android/bluetooth/OobData.java
index d6868e0..2dfa91d 100644
--- a/core/java/android/bluetooth/OobData.java
+++ b/core/java/android/bluetooth/OobData.java
@@ -25,7 +25,6 @@
import com.android.internal.util.Preconditions;
-import java.lang.IllegalArgumentException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -165,68 +164,6 @@
public static final int LE_FLAG_SIMULTANEOUS_HOST = 0x04;
/**
- * Main creation method for creating a Classic version of {@link OobData}.
- *
- * <p>This object will allow the caller to call {@link ClassicBuilder#build()}
- * to build the data object or add any option information to the builder.
- *
- * @param confirmationHash byte array consisting of {@link OobData#CONFIRMATION_OCTETS} octets
- * of data. Data is derived from controller/host stack and is required for pairing OOB.
- * @param classicLength byte array representing the length of data from 8-65535 across 2
- * octets (0xXXXX).
- * @param deviceAddressWithType byte array representing the Bluetooth Address of the device
- * that owns the OOB data. (i.e. the originator) [6 octets]
- *
- * @return a Classic Builder instance with all the given data set or null.
- *
- * @throws IllegalArgumentException if any of the values fail to be set.
- * @throws NullPointerException if any argument is null.
- *
- * @hide
- */
- @NonNull
- @SystemApi
- public static ClassicBuilder createClassicBuilder(@NonNull byte[] confirmationHash,
- @NonNull byte[] classicLength, @NonNull byte[] deviceAddressWithType) {
- return new ClassicBuilder(confirmationHash, classicLength, deviceAddressWithType);
- }
-
- /**
- * Main creation method for creating a LE version of {@link OobData}.
- *
- * <p>This object will allow the caller to call {@link LeBuilder#build()}
- * to build the data object or add any option information to the builder.
- *
- * @param deviceAddressWithType the LE device address plus the address type (7 octets);
- * not null.
- * @param leDeviceRole whether the device supports Peripheral, Central,
- * Both including preference; not null. (1 octet)
- * @param confirmationHash Array consisting of {@link OobData#CONFIRMATION_OCTETS} octets
- * of data. Data is derived from controller/host stack and is
- * required for pairing OOB.
- *
- * <p>Possible LE Device Role Values:
- * 0x00 Only Peripheral supported
- * 0x01 Only Central supported
- * 0x02 Central & Peripheral supported; Peripheral Preferred
- * 0x03 Only peripheral supported; Central Preferred
- * 0x04 - 0xFF Reserved
- *
- * @return a LeBuilder instance with all the given data set or null.
- *
- * @throws IllegalArgumentException if any of the values fail to be set.
- * @throws NullPointerException if any argument is null.
- *
- * @hide
- */
- @NonNull
- @SystemApi
- public static LeBuilder createLeBuilder(@NonNull byte[] confirmationHash,
- @NonNull byte[] deviceAddressWithType, @LeRole int leDeviceRole) {
- return new LeBuilder(confirmationHash, deviceAddressWithType, leDeviceRole);
- }
-
- /**
* Builds an {@link OobData} object and validates that the required combination
* of values are present to create the LE specific OobData type.
*
@@ -342,16 +279,18 @@
private @LeFlag int mLeFlags = LE_FLAG_GENERAL_DISCOVERY_MODE; // Invalid default
/**
- * Constructing an OobData object for use with LE requires
- * a LE Device Address and LE Device Role as well as the Confirmation
- * and optionally, the Randomizer, however it is recommended to use.
+ * Main creation method for creating a LE version of {@link OobData}.
*
- * @param confirmationHash byte array consisting of {@link OobData#CONFIRMATION_OCTETS}
- * octets of data. Data is derived from controller/host stack and is required for
- * pairing OOB.
- * @param deviceAddressWithType 7 bytes containing the 6 byte address with the 1 byte
- * address type.
- * @param leDeviceRole indicating device's role and preferences (Central or Peripheral)
+ * <p>This object will allow the caller to call {@link LeBuilder#build()}
+ * to build the data object or add any option information to the builder.
+ *
+ * @param deviceAddressWithType the LE device address plus the address type (7 octets);
+ * not null.
+ * @param leDeviceRole whether the device supports Peripheral, Central,
+ * Both including preference; not null. (1 octet)
+ * @param confirmationHash Array consisting of {@link OobData#CONFIRMATION_OCTETS} octets
+ * of data. Data is derived from controller/host stack and is
+ * required for pairing OOB.
*
* <p>Possible Values:
* {@link LE_DEVICE_ROLE_PERIPHERAL_ONLY} Only Peripheral supported
@@ -361,11 +300,13 @@
* {@link LE_DEVICE_ROLE_BOTH_PREFER_CENTRAL} Only peripheral supported; Central Preferred
* 0x04 - 0xFF Reserved
*
- * @throws IllegalArgumentException if deviceAddressWithType is not
- * {@link LE_DEVICE_ADDRESS_OCTETS} octets
+ * @throws IllegalArgumentException if any of the values fail to be set.
* @throws NullPointerException if any argument is null.
+ *
+ * @hide
*/
- private LeBuilder(@NonNull byte[] confirmationHash, @NonNull byte[] deviceAddressWithType,
+ @SystemApi
+ public LeBuilder(@NonNull byte[] confirmationHash, @NonNull byte[] deviceAddressWithType,
@LeRole int leDeviceRole) {
Preconditions.checkNotNull(confirmationHash);
Preconditions.checkNotNull(deviceAddressWithType);
@@ -572,25 +513,26 @@
private byte[] mClassOfDevice = null;
/**
+ * Main creation method for creating a Classic version of {@link OobData}.
+ *
+ * <p>This object will allow the caller to call {@link ClassicBuilder#build()}
+ * to build the data object or add any option information to the builder.
+ *
* @param confirmationHash byte array consisting of {@link OobData#CONFIRMATION_OCTETS}
* octets of data. Data is derived from controller/host stack and is required for pairing
* OOB.
- * @param randomizerHash byte array consisting of {@link OobData#RANDOMIZER_OCTETS} octets
- * of data. Data is derived from controller/host stack and is required
- * for pairing OOB. Also, randomizerHash may be all 0s or null in which case
- * it becomes all 0s.
* @param classicLength byte array representing the length of data from 8-65535 across 2
- * octets (0xXXXX). Inclusive of this value in the length.
+ * octets (0xXXXX).
* @param deviceAddressWithType byte array representing the Bluetooth Address of the device
- * that owns the OOB data. (i.e. the originator) [7 octets] this includes the Address Type
- * as the last octet.
+ * that owns the OOB data. (i.e. the originator) [6 octets]
*
- * @throws IllegalArgumentException if any value is not the correct length
- * @throws NullPointerException if anything passed is null
+ * @throws IllegalArgumentException if any of the values fail to be set.
+ * @throws NullPointerException if any argument is null.
*
* @hide
*/
- private ClassicBuilder(@NonNull byte[] confirmationHash, @NonNull byte[] classicLength,
+ @SystemApi
+ public ClassicBuilder(@NonNull byte[] confirmationHash, @NonNull byte[] classicLength,
@NonNull byte[] deviceAddressWithType) {
Preconditions.checkNotNull(confirmationHash);
Preconditions.checkNotNull(classicLength);
diff --git a/core/java/android/bluetooth/le/AdvertisingSet.java b/core/java/android/bluetooth/le/AdvertisingSet.java
index caa91fb..bbdb695 100644
--- a/core/java/android/bluetooth/le/AdvertisingSet.java
+++ b/core/java/android/bluetooth/le/AdvertisingSet.java
@@ -205,10 +205,14 @@
*
* @hide
*/
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
+ @RequiresBluetoothAdvertisePermission
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_ADVERTISE,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+ })
public void getOwnAddress() {
try {
- mGatt.getOwnAddress(mAdvertiserId);
+ mGatt.getOwnAddress(mAdvertiserId, mAttributionSource);
} catch (RemoteException e) {
Log.e(TAG, "remote exception - ", e);
}
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 90105d3..99bbcde 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -3969,6 +3969,7 @@
* @hide
*/
@TestApi
+ @SystemApi
public static final int FLAG_PERMISSION_REVOKE_WHEN_REQUESTED = 1 << 7;
/**
diff --git a/core/java/android/database/sqlite/package.html b/core/java/android/database/sqlite/package.html
index 4d6ba28..6ececa2 100644
--- a/core/java/android/database/sqlite/package.html
+++ b/core/java/android/database/sqlite/package.html
@@ -20,6 +20,9 @@
<p>The version of SQLite depends on the version of Android. See the following table:
<table style="width:auto;">
<tr><th>Android API</th><th>SQLite Version</th></tr>
+ <tr><td>API 31</td><td>3.32</td></tr>
+ <tr><td>API 30</td><td>3.28</td></tr>
+ <tr><td>API 28</td><td>3.22</td></tr>
<tr><td>API 27</td><td>3.19</td></tr>
<tr><td>API 26</td><td>3.18</td></tr>
<tr><td>API 24</td><td>3.9</td></tr>
diff --git a/core/java/android/hardware/Battery.java b/core/java/android/hardware/BatteryState.java
similarity index 91%
rename from core/java/android/hardware/Battery.java
rename to core/java/android/hardware/BatteryState.java
index 24c8d76..aa75359 100644
--- a/core/java/android/hardware/Battery.java
+++ b/core/java/android/hardware/BatteryState.java
@@ -24,9 +24,9 @@
import java.lang.annotation.RetentionPolicy;
/**
- * The Battery class is a representation of a single battery on a device.
+ * The BatteryState class is a representation of a single battery on a device.
*/
-public abstract class Battery {
+public abstract class BatteryState {
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = { "STATUS_" }, value = {
@@ -55,7 +55,7 @@
*
* @return True if the hardware has a battery, else false.
*/
- public abstract boolean hasBattery();
+ public abstract boolean isPresent();
/**
* Get the battery status.
@@ -66,7 +66,7 @@
/**
* Get remaining battery capacity as float percentage [0.0f, 1.0f] of total capacity
- * Returns -1 when battery capacity can't be read.
+ * Returns NaN when battery capacity can't be read.
*
* @return the battery capacity.
*/
diff --git a/core/java/android/hardware/display/BrightnessInfo.java b/core/java/android/hardware/display/BrightnessInfo.java
index 4289860..c5d37c2 100644
--- a/core/java/android/hardware/display/BrightnessInfo.java
+++ b/core/java/android/hardware/display/BrightnessInfo.java
@@ -33,7 +33,8 @@
@IntDef(prefix = {"HIGH_BRIGHTNESS_MODE_"}, value = {
HIGH_BRIGHTNESS_MODE_OFF,
- HIGH_BRIGHTNESS_MODE_SUNLIGHT
+ HIGH_BRIGHTNESS_MODE_SUNLIGHT,
+ HIGH_BRIGHTNESS_MODE_HDR
})
@Retention(RetentionPolicy.SOURCE)
public @interface HighBrightnessMode {}
@@ -50,6 +51,12 @@
*/
public static final int HIGH_BRIGHTNESS_MODE_SUNLIGHT = 1;
+ /**
+ * High brightness mode is ON due to high ambient light (sunlight). The high brightness range is
+ * currently accessible to the user.
+ */
+ public static final int HIGH_BRIGHTNESS_MODE_HDR = 2;
+
/** Brightness */
public final float brightness;
@@ -73,6 +80,21 @@
this.highBrightnessMode = highBrightnessMode;
}
+ /**
+ * @return User-friendly string for specified {@link HighBrightnessMode} parameter.
+ */
+ public static String hbmToString(@HighBrightnessMode int highBrightnessMode) {
+ switch (highBrightnessMode) {
+ case HIGH_BRIGHTNESS_MODE_OFF:
+ return "off";
+ case HIGH_BRIGHTNESS_MODE_HDR:
+ return "hdr";
+ case HIGH_BRIGHTNESS_MODE_SUNLIGHT:
+ return "sunlight";
+ }
+ return "invalid";
+ }
+
@Override
public int describeContents() {
return 0;
diff --git a/core/java/android/hardware/face/FaceEnrollFrame.java b/core/java/android/hardware/face/FaceEnrollFrame.java
index 551139d..822a579 100644
--- a/core/java/android/hardware/face/FaceEnrollFrame.java
+++ b/core/java/android/hardware/face/FaceEnrollFrame.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.hardware.face.FaceEnrollStages.FaceEnrollStage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/hardware/face/FaceEnrollStage.java b/core/java/android/hardware/face/FaceEnrollStage.java
deleted file mode 100644
index de717fb..0000000
--- a/core/java/android/hardware/face/FaceEnrollStage.java
+++ /dev/null
@@ -1,74 +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 android.hardware.face;
-
-import android.annotation.IntDef;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * A stage that may occur during face enrollment.
- *
- * @hide
- */
-@Retention(RetentionPolicy.SOURCE)
-@IntDef({
- FaceEnrollStage.UNKNOWN,
- FaceEnrollStage.FIRST_FRAME_RECEIVED,
- FaceEnrollStage.WAITING_FOR_CENTERING,
- FaceEnrollStage.HOLD_STILL_IN_CENTER,
- FaceEnrollStage.ENROLLING_MOVEMENT_1,
- FaceEnrollStage.ENROLLING_MOVEMENT_2,
- FaceEnrollStage.ENROLLMENT_FINISHED
-})
-public @interface FaceEnrollStage {
- /**
- * The current enrollment stage is not known.
- */
- int UNKNOWN = -1;
-
- /**
- * Enrollment has just begun. No action is needed from the user yet.
- */
- int FIRST_FRAME_RECEIVED = 0;
-
- /**
- * The user must center their face in the frame.
- */
- int WAITING_FOR_CENTERING = 1;
-
- /**
- * The user must keep their face centered in the frame.
- */
- int HOLD_STILL_IN_CENTER = 2;
-
- /**
- * The user must follow a first set of movement instructions.
- */
- int ENROLLING_MOVEMENT_1 = 3;
-
- /**
- * The user must follow a second set of movement instructions.
- */
- int ENROLLING_MOVEMENT_2 = 4;
-
- /**
- * Enrollment has completed. No more action is needed from the user.
- */
- int ENROLLMENT_FINISHED = 5;
-}
diff --git a/core/java/android/hardware/face/FaceEnrollStages.java b/core/java/android/hardware/face/FaceEnrollStages.java
new file mode 100644
index 0000000..de374b3
--- /dev/null
+++ b/core/java/android/hardware/face/FaceEnrollStages.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.face;
+
+import android.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * A collection of constants representing different stages of face enrollment.
+ *
+ * @hide
+ */
+public final class FaceEnrollStages {
+ // Prevent instantiation.
+ private FaceEnrollStages() {}
+
+ /**
+ * A stage that may occur during face enrollment.
+ *
+ * @hide
+ */
+ @IntDef({
+ UNKNOWN,
+ FIRST_FRAME_RECEIVED,
+ WAITING_FOR_CENTERING,
+ HOLD_STILL_IN_CENTER,
+ ENROLLING_MOVEMENT_1,
+ ENROLLING_MOVEMENT_2,
+ ENROLLMENT_FINISHED
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface FaceEnrollStage {}
+
+ /**
+ * The current enrollment stage is not known.
+ */
+ public static final int UNKNOWN = 0;
+
+ /**
+ * Enrollment has just begun. No action is needed from the user yet.
+ */
+ public static final int FIRST_FRAME_RECEIVED = 1;
+
+ /**
+ * The user must center their face in the frame.
+ */
+ public static final int WAITING_FOR_CENTERING = 2;
+
+ /**
+ * The user must keep their face centered in the frame.
+ */
+ public static final int HOLD_STILL_IN_CENTER = 3;
+
+ /**
+ * The user must follow a first set of movement instructions.
+ */
+ public static final int ENROLLING_MOVEMENT_1 = 4;
+
+ /**
+ * The user must follow a second set of movement instructions.
+ */
+ public static final int ENROLLING_MOVEMENT_2 = 5;
+
+ /**
+ * Enrollment has completed. No more action is needed from the user.
+ */
+ public static final int ENROLLMENT_FINISHED = 6;
+}
diff --git a/core/java/android/hardware/face/FaceManager.java b/core/java/android/hardware/face/FaceManager.java
index 5f87899..9a27a99 100644
--- a/core/java/android/hardware/face/FaceManager.java
+++ b/core/java/android/hardware/face/FaceManager.java
@@ -1023,6 +1023,34 @@
}
/**
+ * Called each time a single frame is captured during enrollment.
+ *
+ * <p>For older, non-AIDL implementations, only {@code helpCode} and {@code helpMessage} are
+ * supported. Sensible default values will be provided for all other arguments.
+ *
+ * @param helpCode An integer identifying the capture status for this frame.
+ * @param helpMessage A human-readable help string that can be shown in UI.
+ * @param cell The cell captured during this frame of enrollment, if any.
+ * @param stage An integer representing the current stage of enrollment.
+ * @param pan The horizontal pan of the detected face. Values in the range [-1, 1]
+ * indicate a good capture.
+ * @param tilt The vertical tilt of the detected face. Values in the range [-1, 1]
+ * indicate a good capture.
+ * @param distance The distance of the detected face from the device. Values in
+ * the range [-1, 1] indicate a good capture.
+ */
+ public void onEnrollmentFrame(
+ int helpCode,
+ @Nullable CharSequence helpMessage,
+ @Nullable FaceEnrollCell cell,
+ @FaceEnrollStages.FaceEnrollStage int stage,
+ float pan,
+ float tilt,
+ float distance) {
+ onEnrollmentHelp(helpCode, helpMessage);
+ }
+
+ /**
* Called as each enrollment step progresses. Enrollment is considered complete when
* remaining reaches 0. This function will not be called if enrollment fails. See
* {@link EnrollmentCallback#onEnrollmentError(int, CharSequence)}
@@ -1305,7 +1333,7 @@
} else if (mEnrollmentCallback != null) {
final FaceEnrollFrame frame = new FaceEnrollFrame(
null /* cell */,
- FaceEnrollStage.UNKNOWN,
+ FaceEnrollStages.UNKNOWN,
new FaceDataFrame(acquireInfo, vendorCode));
sendEnrollmentFrame(frame);
}
@@ -1333,12 +1361,19 @@
if (frame == null) {
Slog.w(TAG, "Received null enrollment frame");
} else if (mEnrollmentCallback != null) {
- // TODO(b/178414967): Send additional frame data to callback
- final int acquireInfo = frame.getData().getAcquiredInfo();
- final int vendorCode = frame.getData().getVendorCode();
+ final FaceDataFrame data = frame.getData();
+ final int acquireInfo = data.getAcquiredInfo();
+ final int vendorCode = data.getVendorCode();
final int helpCode = getHelpCode(acquireInfo, vendorCode);
final String helpMessage = getEnrollHelpMessage(mContext, acquireInfo, vendorCode);
- mEnrollmentCallback.onEnrollmentHelp(helpCode, helpMessage);
+ mEnrollmentCallback.onEnrollmentFrame(
+ helpCode,
+ helpMessage,
+ frame.getCell(),
+ frame.getStage(),
+ data.getPan(),
+ data.getTilt(),
+ data.getDistance());
}
}
diff --git a/core/java/android/hardware/input/InputDeviceBattery.java b/core/java/android/hardware/input/InputDeviceBatteryState.java
similarity index 84%
rename from core/java/android/hardware/input/InputDeviceBattery.java
rename to core/java/android/hardware/input/InputDeviceBatteryState.java
index 0fe124e..d069eb0 100644
--- a/core/java/android/hardware/input/InputDeviceBattery.java
+++ b/core/java/android/hardware/input/InputDeviceBatteryState.java
@@ -19,28 +19,28 @@
import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN;
import static android.os.IInputConstants.INVALID_BATTERY_CAPACITY;
-import android.hardware.Battery;
+import android.hardware.BatteryState;
/**
* Battery implementation for input devices.
*
* @hide
*/
-public final class InputDeviceBattery extends Battery {
- private static final float NULL_BATTERY_CAPACITY = -1.0f;
+public final class InputDeviceBatteryState extends BatteryState {
+ private static final float NULL_BATTERY_CAPACITY = Float.NaN;
private final InputManager mInputManager;
private final int mDeviceId;
private final boolean mHasBattery;
- InputDeviceBattery(InputManager inputManager, int deviceId, boolean hasBattery) {
+ InputDeviceBatteryState(InputManager inputManager, int deviceId, boolean hasBattery) {
mInputManager = inputManager;
mDeviceId = deviceId;
mHasBattery = hasBattery;
}
@Override
- public boolean hasBattery() {
+ public boolean isPresent() {
return mHasBattery;
}
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index 648fda7..51d196d 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -1571,12 +1571,12 @@
}
/**
- * Gets a battery object associated with an input device, assuming it has one.
+ * Gets a battery state object associated with an input device, assuming it has one.
* @return The battery, never null.
* @hide
*/
- public InputDeviceBattery getInputDeviceBattery(int deviceId, boolean hasBattery) {
- return new InputDeviceBattery(this, deviceId, hasBattery);
+ public InputDeviceBatteryState getInputDeviceBatteryState(int deviceId, boolean hasBattery) {
+ return new InputDeviceBatteryState(this, deviceId, hasBattery);
}
/**
diff --git a/core/java/android/hardware/lights/Light.java b/core/java/android/hardware/lights/Light.java
index 2c78fcb..2812868 100644
--- a/core/java/android/hardware/lights/Light.java
+++ b/core/java/android/hardware/lights/Light.java
@@ -141,6 +141,11 @@
return mId;
}
+ @Override
+ public String toString() {
+ return "[Name=" + mName + " Id=" + mId + " Type=" + mType + " Ordinal=" + mOrdinal + "]";
+ }
+
/**
* Returns the id of the light.
*
diff --git a/core/java/android/hardware/lights/LightsManager.java b/core/java/android/hardware/lights/LightsManager.java
index cbcef86..2d9bc0e 100644
--- a/core/java/android/hardware/lights/LightsManager.java
+++ b/core/java/android/hardware/lights/LightsManager.java
@@ -113,6 +113,12 @@
private final IBinder mToken = new Binder();
/**
+ * @hide to prevent subclassing from outside of the framework
+ */
+ public LightsSession() {
+ }
+
+ /**
* Sends a request to modify the states of multiple lights.
*
* @param request the settings for lights that should change
diff --git a/core/java/android/view/ContentInfo.java b/core/java/android/view/ContentInfo.java
index b55d9b3..7966712 100644
--- a/core/java/android/view/ContentInfo.java
+++ b/core/java/android/view/ContentInfo.java
@@ -164,6 +164,7 @@
*
* @hide
*/
+ @TestApi
public void releasePermissions() {
if (mInputContentInfo != null) {
mInputContentInfo.releasePermission();
@@ -388,6 +389,8 @@
*
* @hide
*/
+ @TestApi
+ @SuppressLint("MissingGetterMatchingBuilder")
@NonNull
public Builder setInputContentInfo(@Nullable InputContentInfo inputContentInfo) {
mInputContentInfo = inputContentInfo;
@@ -400,6 +403,8 @@
*
* @hide
*/
+ @TestApi
+ @SuppressLint("MissingGetterMatchingBuilder")
@NonNull
public Builder setDragAndDropPermissions(@Nullable DragAndDropPermissions permissions) {
mDragAndDropPermissions = permissions;
diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java
index 3b1c8ec..4f1354d 100644
--- a/core/java/android/view/InputDevice.java
+++ b/core/java/android/view/InputDevice.java
@@ -22,7 +22,7 @@
import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
-import android.hardware.Battery;
+import android.hardware.BatteryState;
import android.hardware.SensorManager;
import android.hardware.input.InputDeviceIdentifier;
import android.hardware.input.InputManager;
@@ -88,7 +88,7 @@
private SensorManager mSensorManager;
@GuardedBy("mMotionRanges")
- private Battery mBattery;
+ private BatteryState mBatteryState;
@GuardedBy("mMotionRanges")
private LightsManager mLightsManager;
@@ -848,19 +848,19 @@
}
/**
- * Gets the battery object associated with the device, if there is one.
+ * Gets the battery state object associated with the device, if there is one.
* Even if the device does not have a battery, the result is never null.
- * Use {@link Battery#hasBattery} to determine whether a battery is
+ * Use {@link BatteryState#isPresent} to determine whether a battery is
* present.
*
* @return The battery object associated with the device, never null.
*/
@NonNull
- public Battery getBattery() {
- if (mBattery == null) {
- mBattery = InputManager.getInstance().getInputDeviceBattery(mId, mHasBattery);
+ public BatteryState getBatteryState() {
+ if (mBatteryState == null) {
+ mBatteryState = InputManager.getInstance().getInputDeviceBatteryState(mId, mHasBattery);
}
- return mBattery;
+ return mBatteryState;
}
/**
diff --git a/core/java/android/view/TEST_MAPPING b/core/java/android/view/TEST_MAPPING
index c8b746f..50d69f7 100644
--- a/core/java/android/view/TEST_MAPPING
+++ b/core/java/android/view/TEST_MAPPING
@@ -20,6 +20,21 @@
}
],
"file_patterns": ["(/|^)ViewConfiguration.java", "(/|^)GestureDetector.java"]
+ },
+ {
+ "name": "CtsViewReceiveContentTestCases",
+ "options": [
+ {
+ "include-annotation": "android.platform.test.annotations.Presubmit"
+ },
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ },
+ {
+ "exclude-annotation": "org.junit.Ignore"
+ }
+ ],
+ "file_patterns": ["ContentInfo\\.java", "OnReceiveContentListener\\.java", "View\\.java"]
}
],
"imports": [
diff --git a/core/java/android/view/contentcapture/MainContentCaptureSession.java b/core/java/android/view/contentcapture/MainContentCaptureSession.java
index f196f75..ad4ba76 100644
--- a/core/java/android/view/contentcapture/MainContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/MainContentCaptureSession.java
@@ -583,9 +583,9 @@
// NOTE: we must save a reference to the current mEvents and then set it to to null,
// otherwise clearing it would clear it in the receiving side if the service is also local.
final List<ContentCaptureEvent> events = mEvents == null
- ? Collections.emptyList()
- : mEvents;
- mEvents = null;
+ ? Collections.EMPTY_LIST
+ : new ArrayList<>(mEvents);
+ mEvents.clear();
mLastComposingSpan.clear();
return new ParceledListSlice<>(events);
}
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 20a0b0b..6694b7e 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -2259,7 +2259,8 @@
if (servedView == null || servedView.getWindowToken() != windowToken) {
return false;
}
- showSoftInput(servedView, 0 /* flags */, null /* resultReceiver */);
+ showSoftInput(servedView, 0 /* flags */, null /* resultReceiver */,
+ SoftInputShowHideReason.SHOW_SOFT_INPUT_BY_INSETS_API);
return true;
}
}
diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java
index b5a5848..e41893e 100644
--- a/core/java/android/widget/HorizontalScrollView.java
+++ b/core/java/android/widget/HorizontalScrollView.java
@@ -47,6 +47,7 @@
import android.view.inspector.InspectableProperty;
import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
import java.util.List;
@@ -86,19 +87,23 @@
*
* Even though this field is practically final, we cannot make it final because there are apps
* setting it via reflection and they need to keep working until they target Q.
+ * @hide
*/
@NonNull
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124053130)
- private EdgeEffect mEdgeGlowLeft;
+ @VisibleForTesting
+ public EdgeEffect mEdgeGlowLeft;
/**
* Tracks the state of the bottom edge glow.
*
* Even though this field is practically final, we cannot make it final because there are apps
* setting it via reflection and they need to keep working until they target Q.
+ * @hide
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124052619)
- private EdgeEffect mEdgeGlowRight;
+ @VisibleForTesting
+ public EdgeEffect mEdgeGlowRight;
/**
* Position of the last motion event.
@@ -774,11 +779,8 @@
// Calling overScrollBy will call onOverScrolled, which
// calls onScrollChanged if applicable.
- if (overScrollBy(deltaX, 0, mScrollX, 0, range, 0,
- mOverscrollDistance, 0, true)) {
- // Break our velocity if we hit a scroll barrier.
- mVelocityTracker.clear();
- }
+ overScrollBy(deltaX, 0, mScrollX, 0, range, 0,
+ mOverscrollDistance, 0, true);
if (canOverscroll && deltaX != 0f) {
final int pulledToX = oldX + deltaX;
@@ -1737,23 +1739,31 @@
public void fling(int velocityX) {
if (getChildCount() > 0) {
int width = getWidth() - mPaddingRight - mPaddingLeft;
- int right = getChildAt(0).getWidth();
+ int right = getChildAt(0).getRight() - mPaddingLeft;
- mScroller.fling(mScrollX, mScrollY, velocityX, 0, 0,
- Math.max(0, right - width), 0, 0, width/2, 0);
+ int maxScroll = Math.max(0, right - width);
- final boolean movingRight = velocityX > 0;
+ if (mScrollX == 0 && !mEdgeGlowLeft.isFinished()) {
+ mEdgeGlowLeft.onAbsorb(-velocityX);
+ } else if (mScrollX == maxScroll && !mEdgeGlowRight.isFinished()) {
+ mEdgeGlowRight.onAbsorb(velocityX);
+ } else {
+ mScroller.fling(mScrollX, mScrollY, velocityX, 0, 0,
+ maxScroll, 0, 0, width / 2, 0);
- View currentFocused = findFocus();
- View newFocused = findFocusableViewInMyBounds(movingRight,
- mScroller.getFinalX(), currentFocused);
+ final boolean movingRight = velocityX > 0;
- if (newFocused == null) {
- newFocused = this;
- }
+ View currentFocused = findFocus();
+ View newFocused = findFocusableViewInMyBounds(movingRight,
+ mScroller.getFinalX(), currentFocused);
- if (newFocused != currentFocused) {
- newFocused.requestFocus(movingRight ? View.FOCUS_RIGHT : View.FOCUS_LEFT);
+ if (newFocused == null) {
+ newFocused = this;
+ }
+
+ if (newFocused != currentFocused) {
+ newFocused.requestFocus(movingRight ? View.FOCUS_RIGHT : View.FOCUS_LEFT);
+ }
}
postInvalidateOnAnimation();
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index 2dd7f02..3610eb4 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -49,6 +49,7 @@
import android.view.inspector.InspectableProperty;
import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
import java.util.List;
@@ -95,20 +96,24 @@
*
* Even though this field is practically final, we cannot make it final because there are apps
* setting it via reflection and they need to keep working until they target Q.
+ * @hide
*/
@NonNull
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768600)
- private EdgeEffect mEdgeGlowTop;
+ @VisibleForTesting
+ public EdgeEffect mEdgeGlowTop;
/**
* Tracks the state of the bottom edge glow.
*
* Even though this field is practically final, we cannot make it final because there are apps
* setting it via reflection and they need to keep working until they target Q.
+ * @hide
*/
@NonNull
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123769386)
- private EdgeEffect mEdgeGlowBottom;
+ @VisibleForTesting
+ public EdgeEffect mEdgeGlowBottom;
/**
* Position of the last motion event.
@@ -1791,9 +1796,15 @@
final boolean canFling = (mScrollY > 0 || velocityY > 0) &&
(mScrollY < getScrollRange() || velocityY < 0);
if (!dispatchNestedPreFling(0, velocityY)) {
- dispatchNestedFling(0, velocityY, canFling);
+ final boolean consumed = dispatchNestedFling(0, velocityY, canFling);
if (canFling) {
fling(velocityY);
+ } else if (!consumed) {
+ if (!mEdgeGlowTop.isFinished()) {
+ mEdgeGlowTop.onAbsorb(-velocityY);
+ } else if (!mEdgeGlowBottom.isFinished()) {
+ mEdgeGlowBottom.onAbsorb(velocityY);
+ }
}
}
}
diff --git a/core/java/com/android/internal/accessibility/dialog/AccessibilityTarget.java b/core/java/com/android/internal/accessibility/dialog/AccessibilityTarget.java
index d84175e..5b0abd3 100644
--- a/core/java/com/android/internal/accessibility/dialog/AccessibilityTarget.java
+++ b/core/java/com/android/internal/accessibility/dialog/AccessibilityTarget.java
@@ -24,6 +24,7 @@
import static com.android.internal.accessibility.util.ShortcutUtils.optOutValueFromSettings;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.view.View;
@@ -33,6 +34,7 @@
import com.android.internal.accessibility.common.ShortcutConstants;
import com.android.internal.accessibility.common.ShortcutConstants.AccessibilityFragmentType;
import com.android.internal.accessibility.dialog.TargetAdapter.ViewHolder;
+import com.android.internal.annotations.VisibleForTesting;
/**
* Abstract base class for creating various target related to accessibility service,
@@ -51,7 +53,8 @@
private Drawable mIcon;
private String mKey;
- AccessibilityTarget(Context context, @ShortcutType int shortcutType,
+ @VisibleForTesting
+ public AccessibilityTarget(Context context, @ShortcutType int shortcutType,
@AccessibilityFragmentType int fragmentType, boolean isShortcutSwitched, String id,
CharSequence label, Drawable icon, String key) {
mContext = context;
@@ -103,6 +106,16 @@
}
}
+ /**
+ * Gets the state description of this feature target.
+ *
+ * @return the state description
+ */
+ @Nullable
+ public CharSequence getStateDescription() {
+ return null;
+ }
+
public void setShortcutEnabled(boolean enabled) {
mShortcutEnabled = enabled;
}
diff --git a/core/java/com/android/internal/accessibility/dialog/ToggleAccessibilityServiceTarget.java b/core/java/com/android/internal/accessibility/dialog/ToggleAccessibilityServiceTarget.java
index 239e531..469d10f 100644
--- a/core/java/com/android/internal/accessibility/dialog/ToggleAccessibilityServiceTarget.java
+++ b/core/java/com/android/internal/accessibility/dialog/ToggleAccessibilityServiceTarget.java
@@ -51,10 +51,14 @@
final boolean isEditMenuMode =
shortcutMenuMode == ShortcutMenuMode.EDIT;
holder.mStatusView.setVisibility(isEditMenuMode ? View.GONE : View.VISIBLE);
+ holder.mStatusView.setText(getStateDescription());
+ }
+ @Override
+ public CharSequence getStateDescription() {
final int statusResId = isAccessibilityServiceEnabled(getContext(), getId())
? R.string.accessibility_shortcut_menu_item_status_on
: R.string.accessibility_shortcut_menu_item_status_off;
- holder.mStatusView.setText(getContext().getString(statusResId));
+ return getContext().getString(statusResId);
}
}
diff --git a/core/java/com/android/internal/accessibility/dialog/ToggleAllowListingFeatureTarget.java b/core/java/com/android/internal/accessibility/dialog/ToggleAllowListingFeatureTarget.java
index 38aac70..ebdaed6 100644
--- a/core/java/com/android/internal/accessibility/dialog/ToggleAllowListingFeatureTarget.java
+++ b/core/java/com/android/internal/accessibility/dialog/ToggleAllowListingFeatureTarget.java
@@ -48,11 +48,15 @@
final boolean isEditMenuMode =
shortcutMenuMode == ShortcutMenuMode.EDIT;
holder.mStatusView.setVisibility(isEditMenuMode ? View.GONE : View.VISIBLE);
+ holder.mStatusView.setText(getStateDescription());
+ }
+ @Override
+ public CharSequence getStateDescription() {
final int statusResId = isFeatureEnabled()
? R.string.accessibility_shortcut_menu_item_status_on
: R.string.accessibility_shortcut_menu_item_status_off;
- holder.mStatusView.setText(getContext().getString(statusResId));
+ return getContext().getString(statusResId);
}
private boolean isFeatureEnabled() {
diff --git a/core/java/com/android/internal/app/procstats/AssociationState.java b/core/java/com/android/internal/app/procstats/AssociationState.java
index 8fef837..4133c4d 100644
--- a/core/java/com/android/internal/app/procstats/AssociationState.java
+++ b/core/java/com/android/internal/app/procstats/AssociationState.java
@@ -16,8 +16,10 @@
package com.android.internal.app.procstats;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcel;
+import android.os.Parcelable;
import android.os.SystemClock;
import android.os.UserHandle;
import android.service.procstats.PackageAssociationProcessStatsProto;
@@ -54,7 +56,14 @@
private int mTotalActiveCount;
private long mTotalActiveDuration;
- public final class SourceState {
+ /**
+ * The state of the source process of an association.
+ */
+ public static final class SourceState implements Parcelable {
+ private @NonNull final ProcessStats mProcessStats;
+ private @Nullable final AssociationState mAssociationState;
+ private @Nullable final ProcessState mTargetProcess;
+ private @Nullable SourceState mCommonSourceState;
final SourceKey mKey;
int mProcStateSeq = -1;
int mProcState = ProcessStats.STATE_NOTHING;
@@ -64,18 +73,24 @@
long mStartUptime;
long mDuration;
long mTrackingUptime;
+ int mActiveNesting;
int mActiveCount;
int mActiveProcState = ProcessStats.STATE_NOTHING;
long mActiveStartUptime;
long mActiveDuration;
DurationsTable mActiveDurations;
- SourceState(SourceKey key) {
+ SourceState(@NonNull ProcessStats processStats, @Nullable AssociationState associationState,
+ @NonNull ProcessState targetProcess, SourceKey key) {
+ mProcessStats = processStats;
+ mAssociationState = associationState;
+ mTargetProcess = targetProcess;
mKey = key;
}
+ @Nullable
public AssociationState getAssociationState() {
- return AssociationState.this;
+ return mAssociationState;
}
public String getProcessName() {
@@ -86,7 +101,20 @@
return mKey.mUid;
}
+ @Nullable
+ private SourceState getCommonSourceState(boolean createIfNeeded) {
+ if (mCommonSourceState == null) {
+ if (createIfNeeded) {
+ mCommonSourceState = mTargetProcess.getOrCreateSourceState(mKey);
+ } else {
+ Slog.wtf(TAG, "Unable to find common source state for " + mKey.mProcess);
+ }
+ }
+ return mCommonSourceState;
+ }
+
public void trackProcState(int procState, int seq, long now) {
+ final int processState = procState;
procState = ProcessState.PROCESS_STATE_TO_STATE[procState];
if (seq != mProcStateSeq) {
mProcStateSeq = seq;
@@ -102,30 +130,81 @@
if (!mInTrackingList) {
mInTrackingList = true;
mTrackingUptime = now;
- mProcessStats.mTrackingAssociations.add(this);
+ if (mAssociationState != null) {
+ mProcessStats.mTrackingAssociations.add(this);
+ }
+ }
+ }
+ if (mAssociationState != null) {
+ final SourceState commonSource = getCommonSourceState(true);
+ if (commonSource != null) {
+ commonSource.trackProcState(processState, seq, now);
}
}
}
+ long start() {
+ final long now = start(-1);
+ if (mAssociationState != null) {
+ final SourceState commonSource = getCommonSourceState(true);
+ if (commonSource != null) {
+ commonSource.start(now);
+ }
+ }
+ return now;
+ }
+
+ long start(long now) {
+ mNesting++;
+ if (mNesting == 1) {
+ if (now < 0) {
+ now = SystemClock.uptimeMillis();
+ }
+ mCount++;
+ mStartUptime = now;
+ }
+ return now;
+ }
+
public void stop() {
- mNesting--;
- if (mNesting == 0) {
- final long now = SystemClock.uptimeMillis();
- mDuration += now - mStartUptime;
- stopTracking(now);
+ final long now = stop(-1);
+ if (mAssociationState != null) {
+ final SourceState commonSource = getCommonSourceState(false);
+ if (commonSource != null) {
+ commonSource.stop(now);
+ }
}
}
+ long stop(long now) {
+ mNesting--;
+ if (mNesting == 0) {
+ if (now < 0) {
+ now = SystemClock.uptimeMillis();
+ }
+ mDuration += now - mStartUptime;
+ stopTracking(now);
+ }
+ return now;
+ }
+
void startActive(long now) {
+ boolean startActive = false;
if (mInTrackingList) {
if (mActiveStartUptime == 0) {
mActiveStartUptime = now;
+ mActiveNesting++;
mActiveCount++;
- AssociationState.this.mTotalActiveNesting++;
- if (AssociationState.this.mTotalActiveNesting == 1) {
- AssociationState.this.mTotalActiveCount++;
- AssociationState.this.mTotalActiveStartUptime = now;
+ startActive = true;
+ if (mAssociationState != null) {
+ mAssociationState.mTotalActiveNesting++;
+ if (mAssociationState.mTotalActiveNesting == 1) {
+ mAssociationState.mTotalActiveCount++;
+ mAssociationState.mTotalActiveStartUptime = now;
+ }
}
+ } else if (mAssociationState == null) {
+ mActiveNesting++;
}
if (mActiveProcState != mProcState) {
if (mActiveProcState != ProcessStats.STATE_NOTHING) {
@@ -133,6 +212,9 @@
// so far and switch tracking to the new proc state.
final long addedDuration = mActiveDuration + now - mActiveStartUptime;
mActiveStartUptime = now;
+ if (mAssociationState != null) {
+ startActive = true;
+ }
if (addedDuration != 0) {
if (mActiveDurations == null) {
makeDurations();
@@ -146,68 +228,233 @@
} else {
Slog.wtf(TAG, "startActive while not tracking: " + this);
}
+ if (mAssociationState != null) {
+ final SourceState commonSource = getCommonSourceState(true);
+ if (commonSource != null && startActive) {
+ commonSource.startActive(now);
+ }
+ }
}
void stopActive(long now) {
+ boolean stopActive = false;
if (mActiveStartUptime != 0) {
- if (!mInTrackingList) {
+ if (!mInTrackingList && mAssociationState != null) {
Slog.wtf(TAG, "stopActive while not tracking: " + this);
}
+ mActiveNesting--;
final long addedDuration = now - mActiveStartUptime;
- mActiveStartUptime = 0;
+ mActiveStartUptime = mAssociationState != null || mActiveNesting == 0 ? 0 : now;
+ stopActive = mActiveStartUptime == 0;
if (mActiveDurations != null) {
mActiveDurations.addDuration(mActiveProcState, addedDuration);
} else {
mActiveDuration += addedDuration;
}
- AssociationState.this.mTotalActiveNesting--;
- if (AssociationState.this.mTotalActiveNesting == 0) {
- AssociationState.this.mTotalActiveDuration += now
- - AssociationState.this.mTotalActiveStartUptime;
- AssociationState.this.mTotalActiveStartUptime = 0;
- if (VALIDATE_TIMES) {
- if (mActiveDuration > AssociationState.this.mTotalActiveDuration) {
- RuntimeException ex = new RuntimeException();
- ex.fillInStackTrace();
- Slog.w(TAG, "Source act duration " + mActiveDurations
- + " exceeds total " + AssociationState.this.mTotalActiveDuration
- + " in procstate " + mActiveProcState + " in source "
- + mKey.mProcess + " to assoc "
- + AssociationState.this.mName, ex);
- }
+ if (mAssociationState != null) {
+ mAssociationState.mTotalActiveNesting--;
+ if (mAssociationState.mTotalActiveNesting == 0) {
+ mAssociationState.mTotalActiveDuration += now
+ - mAssociationState.mTotalActiveStartUptime;
+ mAssociationState.mTotalActiveStartUptime = 0;
+ if (VALIDATE_TIMES) {
+ if (mActiveDuration > mAssociationState.mTotalActiveDuration) {
+ RuntimeException ex = new RuntimeException();
+ ex.fillInStackTrace();
+ Slog.w(TAG, "Source act duration " + mActiveDurations
+ + " exceeds total " + mAssociationState.mTotalActiveDuration
+ + " in procstate " + mActiveProcState + " in source "
+ + mKey.mProcess + " to assoc "
+ + mAssociationState.mName, ex);
+ }
+ }
}
}
}
+
+ if (mAssociationState != null) {
+ final SourceState commonSource = getCommonSourceState(false);
+ if (commonSource != null && stopActive) {
+ commonSource.stopActive(now);
+ }
+ }
+ }
+
+ boolean stopActiveIfNecessary(int curSeq, long now) {
+ if (mProcStateSeq != curSeq || mProcState >= ProcessStats.STATE_HOME) {
+ // If this association did not get touched the last time we computed
+ // process states, or its state ended up down in cached, then we no
+ // longer have a reason to track it at all.
+ stopActive(now);
+ stopTrackingProcState();
+ return true;
+ }
+ return false;
+ }
+
+ private void stopTrackingProcState() {
+ mInTrackingList = false;
+ mProcState = ProcessStats.STATE_NOTHING;
+ if (mAssociationState != null) {
+ final SourceState commonSource = getCommonSourceState(false);
+ if (commonSource != null) {
+ commonSource.stopTrackingProcState();
+ }
+ }
+ }
+
+ boolean isInUse() {
+ return mNesting > 0;
+ }
+
+ void resetSafely(long now) {
+ if (isInUse()) {
+ mCount = 1;
+ mStartUptime = now;
+ mDuration = 0;
+ if (mActiveStartUptime > 0) {
+ mActiveCount = 1;
+ mActiveStartUptime = now;
+ } else {
+ mActiveCount = 0;
+ }
+ mActiveDuration = 0;
+ mActiveDurations = null;
+ }
+ }
+
+ void commitStateTime(long nowUptime) {
+ if (mNesting > 0) {
+ mDuration += nowUptime - mStartUptime;
+ mStartUptime = nowUptime;
+ }
+ if (mActiveStartUptime > 0) {
+ final long addedDuration = nowUptime - mActiveStartUptime;
+ mActiveStartUptime = nowUptime;
+ if (mActiveDurations != null) {
+ mActiveDurations.addDuration(mActiveProcState, addedDuration);
+ } else {
+ mActiveDuration += addedDuration;
+ }
+ }
}
void makeDurations() {
mActiveDurations = new DurationsTable(mProcessStats.mTableData);
}
- void stopTracking(long now) {
- AssociationState.this.mTotalNesting--;
- if (AssociationState.this.mTotalNesting == 0) {
- AssociationState.this.mTotalDuration += now
- - AssociationState.this.mTotalStartUptime;
+ private void stopTracking(long now) {
+ if (mAssociationState != null) {
+ mAssociationState.mTotalNesting--;
+ if (mAssociationState.mTotalNesting == 0) {
+ mAssociationState.mTotalDuration += now
+ - mAssociationState.mTotalStartUptime;
+ }
}
stopActive(now);
if (mInTrackingList) {
mInTrackingList = false;
mProcState = ProcessStats.STATE_NOTHING;
- // Do a manual search for where to remove, since these objects will typically
- // be towards the end of the array.
- final ArrayList<SourceState> list = mProcessStats.mTrackingAssociations;
- for (int i = list.size() - 1; i >= 0; i--) {
- if (list.get(i) == this) {
- list.remove(i);
- return;
+ if (mAssociationState != null) {
+ // Do a manual search for where to remove, since these objects will typically
+ // be towards the end of the array.
+ final ArrayList<SourceState> list = mProcessStats.mTrackingAssociations;
+ for (int i = list.size() - 1; i >= 0; i--) {
+ if (list.get(i) == this) {
+ list.remove(i);
+ return;
+ }
}
+ Slog.wtf(TAG, "Stop tracking didn't find in tracking list: " + this);
}
- Slog.wtf(TAG, "Stop tracking didn't find in tracking list: " + this);
}
}
+ void add(SourceState otherSrc) {
+ mCount += otherSrc.mCount;
+ mDuration += otherSrc.mDuration;
+ mActiveCount += otherSrc.mActiveCount;
+ if (otherSrc.mActiveDuration != 0 || otherSrc.mActiveDurations != null) {
+ // Only need to do anything if the other one has some duration data.
+ if (mActiveDurations != null) {
+ // If the target already has multiple durations, just add in whatever
+ // we have in the other.
+ if (otherSrc.mActiveDurations != null) {
+ mActiveDurations.addDurations(otherSrc.mActiveDurations);
+ } else {
+ mActiveDurations.addDuration(otherSrc.mActiveProcState,
+ otherSrc.mActiveDuration);
+ }
+ } else if (otherSrc.mActiveDurations != null) {
+ // The other one has multiple durations, but we don't. Expand to
+ // multiple durations and copy over.
+ makeDurations();
+ mActiveDurations.addDurations(otherSrc.mActiveDurations);
+ if (mActiveDuration != 0) {
+ mActiveDurations.addDuration(mActiveProcState, mActiveDuration);
+ mActiveDuration = 0;
+ mActiveProcState = ProcessStats.STATE_NOTHING;
+ }
+ } else if (mActiveDuration != 0) {
+ // Both have a single inline duration... we can either add them together,
+ // or need to expand to multiple durations.
+ if (mActiveProcState == otherSrc.mActiveProcState) {
+ mActiveDuration += otherSrc.mActiveDuration;
+ } else {
+ // The two have durations with different proc states, need to turn
+ // in to multiple durations.
+ makeDurations();
+ mActiveDurations.addDuration(mActiveProcState, mActiveDuration);
+ mActiveDurations.addDuration(otherSrc.mActiveProcState,
+ otherSrc.mActiveDuration);
+ mActiveDuration = 0;
+ mActiveProcState = ProcessStats.STATE_NOTHING;
+ }
+ } else {
+ // The other one has a duration, and we know the target doesn't. Copy over.
+ mActiveProcState = otherSrc.mActiveProcState;
+ mActiveDuration = otherSrc.mActiveDuration;
+ }
+ }
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeInt(mCount);
+ out.writeLong(mDuration);
+ out.writeInt(mActiveCount);
+ if (mActiveDurations != null) {
+ out.writeInt(1);
+ mActiveDurations.writeToParcel(out);
+ } else {
+ out.writeInt(0);
+ out.writeInt(mActiveProcState);
+ out.writeLong(mActiveDuration);
+ }
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ String readFromParcel(Parcel in) {
+ mCount = in.readInt();
+ mDuration = in.readLong();
+ mActiveCount = in.readInt();
+ if (in.readInt() != 0) {
+ makeDurations();
+ if (!mActiveDurations.readFromParcel(in)) {
+ return "Duration table corrupt: " + mKey + " <- " + toString();
+ }
+ } else {
+ mActiveProcState = in.readInt();
+ mActiveDuration = in.readLong();
+ }
+ return null;
+ }
+
@Override
public String toString() {
StringBuilder sb = new StringBuilder(64);
@@ -222,7 +469,7 @@
}
}
- public final class SourceDumpContainer {
+ static final class SourceDumpContainer {
public final SourceState mState;
public long mTotalTime;
public long mActiveTime;
@@ -256,6 +503,18 @@
mPackage = pkg;
}
+ SourceKey(ProcessStats stats, Parcel in, int parcelVersion) {
+ mUid = in.readInt();
+ mProcess = stats.readCommonString(in, parcelVersion);
+ mPackage = stats.readCommonString(in, parcelVersion);
+ }
+
+ void writeToParcel(ProcessStats stats, Parcel out) {
+ out.writeInt(mUid);
+ stats.writeCommonString(out, mProcess);
+ stats.writeCommonString(out, mPackage);
+ }
+
public boolean equals(Object o) {
if (!(o instanceof SourceKey)) {
return false;
@@ -347,14 +606,11 @@
}
if (src == null) {
SourceKey key = new SourceKey(uid, processName, packageName);
- src = new SourceState(key);
+ src = new SourceState(mProcessStats, this, mProc, key);
mSources.put(key, src);
}
- src.mNesting++;
- if (src.mNesting == 1) {
- final long now = SystemClock.uptimeMillis();
- src.mCount++;
- src.mStartUptime = now;
+ final long now = src.start();
+ if (now > 0) {
mTotalNesting++;
if (mTotalNesting == 1) {
mTotalCount++;
@@ -376,7 +632,7 @@
SourceState mySrc = mSources.get(key);
boolean newSrc = false;
if (mySrc == null) {
- mySrc = new SourceState(key);
+ mySrc = new SourceState(mProcessStats, this, mProc, key);
mSources.put(key, mySrc);
newSrc = true;
}
@@ -412,53 +668,7 @@
}
}
}
- mySrc.mCount += otherSrc.mCount;
- mySrc.mDuration += otherSrc.mDuration;
- mySrc.mActiveCount += otherSrc.mActiveCount;
- if (otherSrc.mActiveDuration != 0 || otherSrc.mActiveDurations != null) {
- // Only need to do anything if the other one has some duration data.
- if (mySrc.mActiveDurations != null) {
- // If the target already has multiple durations, just add in whatever
- // we have in the other.
- if (otherSrc.mActiveDurations != null) {
- mySrc.mActiveDurations.addDurations(otherSrc.mActiveDurations);
- } else {
- mySrc.mActiveDurations.addDuration(otherSrc.mActiveProcState,
- otherSrc.mActiveDuration);
- }
- } else if (otherSrc.mActiveDurations != null) {
- // The other one has multiple durations, but we don't. Expand to
- // multiple durations and copy over.
- mySrc.makeDurations();
- mySrc.mActiveDurations.addDurations(otherSrc.mActiveDurations);
- if (mySrc.mActiveDuration != 0) {
- mySrc.mActiveDurations.addDuration(mySrc.mActiveProcState,
- mySrc.mActiveDuration);
- mySrc.mActiveDuration = 0;
- mySrc.mActiveProcState = ProcessStats.STATE_NOTHING;
- }
- } else if (mySrc.mActiveDuration != 0) {
- // Both have a single inline duration... we can either add them together,
- // or need to expand to multiple durations.
- if (mySrc.mActiveProcState == otherSrc.mActiveProcState) {
- mySrc.mActiveDuration += otherSrc.mActiveDuration;
- } else {
- // The two have durations with different proc states, need to turn
- // in to multiple durations.
- mySrc.makeDurations();
- mySrc.mActiveDurations.addDuration(mySrc.mActiveProcState,
- mySrc.mActiveDuration);
- mySrc.mActiveDurations.addDuration(otherSrc.mActiveProcState,
- otherSrc.mActiveDuration);
- mySrc.mActiveDuration = 0;
- mySrc.mActiveProcState = ProcessStats.STATE_NOTHING;
- }
- } else {
- // The other one has a duration, and we know the target doesn't. Copy over.
- mySrc.mActiveProcState = otherSrc.mActiveProcState;
- mySrc.mActiveDuration = otherSrc.mActiveDuration;
- }
- }
+ mySrc.add(otherSrc);
}
}
@@ -474,18 +684,8 @@
// We have some active sources... clear out everything but those.
for (int isrc = mSources.size() - 1; isrc >= 0; isrc--) {
SourceState src = mSources.valueAt(isrc);
- if (src.mNesting > 0) {
- src.mCount = 1;
- src.mStartUptime = now;
- src.mDuration = 0;
- if (src.mActiveStartUptime > 0) {
- src.mActiveCount = 1;
- src.mActiveStartUptime = now;
- } else {
- src.mActiveCount = 0;
- }
- src.mActiveDuration = 0;
- src.mActiveDurations = null;
+ if (src.isInUse()) {
+ src.resetSafely(now);
} else {
mSources.removeAt(isrc);
}
@@ -512,20 +712,8 @@
for (int isrc = 0; isrc < NSRC; isrc++) {
final SourceKey key = mSources.keyAt(isrc);
final SourceState src = mSources.valueAt(isrc);
- out.writeInt(key.mUid);
- stats.writeCommonString(out, key.mProcess);
- stats.writeCommonString(out, key.mPackage);
- out.writeInt(src.mCount);
- out.writeLong(src.mDuration);
- out.writeInt(src.mActiveCount);
- if (src.mActiveDurations != null) {
- out.writeInt(1);
- src.mActiveDurations.writeToParcel(out);
- } else {
- out.writeInt(0);
- out.writeInt(src.mActiveProcState);
- out.writeLong(src.mActiveDuration);
- }
+ key.writeToParcel(stats, out);
+ src.writeToParcel(out, 0);
}
}
@@ -543,22 +731,11 @@
return "Association with bad src count: " + NSRC;
}
for (int isrc = 0; isrc < NSRC; isrc++) {
- final int uid = in.readInt();
- final String procName = stats.readCommonString(in, parcelVersion);
- final String pkgName = stats.readCommonString(in, parcelVersion);
- final SourceKey key = new SourceKey(uid, procName, pkgName);
- final SourceState src = new SourceState(key);
- src.mCount = in.readInt();
- src.mDuration = in.readLong();
- src.mActiveCount = in.readInt();
- if (in.readInt() != 0) {
- src.makeDurations();
- if (!src.mActiveDurations.readFromParcel(in)) {
- return "Duration table corrupt: " + key + " <- " + src;
- }
- } else {
- src.mActiveProcState = in.readInt();
- src.mActiveDuration = in.readLong();
+ final SourceKey key = new SourceKey(stats, in, parcelVersion);
+ final SourceState src = new SourceState(mProcessStats, this, mProc, key);
+ final String errMsg = src.readFromParcel(in);
+ if (errMsg != null) {
+ return errMsg;
}
if (VALIDATE_TIMES) {
if (src.mDuration > mTotalDuration) {
@@ -585,19 +762,7 @@
if (isInUse()) {
for (int isrc = mSources.size() - 1; isrc >= 0; isrc--) {
SourceState src = mSources.valueAt(isrc);
- if (src.mNesting > 0) {
- src.mDuration += nowUptime - src.mStartUptime;
- src.mStartUptime = nowUptime;
- }
- if (src.mActiveStartUptime > 0) {
- final long addedDuration = nowUptime - src.mActiveStartUptime;
- src.mActiveStartUptime = nowUptime;
- if (src.mActiveDurations != null) {
- src.mActiveDurations.addDuration(src.mActiveProcState, addedDuration);
- } else {
- src.mActiveDuration += addedDuration;
- }
- }
+ src.commitStateTime(nowUptime);
}
if (mTotalNesting > 0) {
mTotalDuration += nowUptime - mTotalStartUptime;
@@ -644,12 +809,12 @@
return 0;
};
- public ArrayList<Pair<SourceKey, SourceDumpContainer>> createSortedAssociations(long now,
- long totalTime) {
- final int NSRC = mSources.size();
- ArrayList<Pair<SourceKey, SourceDumpContainer>> sources = new ArrayList<>(NSRC);
- for (int isrc = 0; isrc < NSRC; isrc++) {
- final SourceState src = mSources.valueAt(isrc);
+ static ArrayList<Pair<SourceKey, SourceDumpContainer>> createSortedAssociations(long now,
+ long totalTime, ArrayMap<SourceKey, SourceState> inSources) {
+ final int numOfSources = inSources.size();
+ ArrayList<Pair<SourceKey, SourceDumpContainer>> sources = new ArrayList<>(numOfSources);
+ for (int isrc = 0; isrc < numOfSources; isrc++) {
+ final SourceState src = inSources.valueAt(isrc);
final SourceDumpContainer cont = new SourceDumpContainer(src);
long duration = src.mDuration;
if (src.mNesting > 0) {
@@ -660,7 +825,7 @@
if (cont.mActiveTime < 0) {
cont.mActiveTime = -cont.mActiveTime;
}
- sources.add(new Pair<>(mSources.keyAt(isrc), cont));
+ sources.add(new Pair<>(inSources.keyAt(isrc), cont));
}
Collections.sort(sources, ASSOCIATION_COMPARATOR);
return sources;
@@ -722,6 +887,14 @@
TimeUtils.formatDuration(mTotalStartUptime, now, pw);
pw.println();
}
+
+ dumpSources(pw, prefix, prefixInner, prefixInnerInner, sources, now, totalTime,
+ reqPackage, dumpDetails, dumpAll);
+ }
+
+ static void dumpSources(PrintWriter pw, String prefix, String prefixInner,
+ String prefixInnerInner, ArrayList<Pair<SourceKey, SourceDumpContainer>> sources,
+ long now, long totalTime, String reqPackage, boolean dumpDetails, boolean dumpAll) {
final int NSRC = sources.size();
for (int isrc = 0; isrc < NSRC; isrc++) {
final SourceKey key = sources.get(isrc).first;
@@ -826,7 +999,7 @@
}
}
- void dumpActiveDurationSummary(PrintWriter pw, final SourceState src, long totalTime,
+ static void dumpActiveDurationSummary(PrintWriter pw, final SourceState src, long totalTime,
long now, boolean dumpAll) {
long duration = dumpTime(null, null, src, totalTime, now, false, false);
final boolean isRunning = duration < 0;
@@ -846,8 +1019,8 @@
pw.println();
}
- long dumpTime(PrintWriter pw, String prefix, final SourceState src, long overallTime, long now,
- boolean dumpDetails, boolean dumpAll) {
+ static long dumpTime(PrintWriter pw, String prefix, final SourceState src, long overallTime,
+ long now, boolean dumpDetails, boolean dumpAll) {
long totalTime = 0;
boolean isRunning = false;
for (int iprocstate = 0; iprocstate < ProcessStats.STATE_COUNT; iprocstate++) {
diff --git a/core/java/com/android/internal/app/procstats/DumpUtils.java b/core/java/com/android/internal/app/procstats/DumpUtils.java
index b476a17..2785c21 100644
--- a/core/java/com/android/internal/app/procstats/DumpUtils.java
+++ b/core/java/com/android/internal/app/procstats/DumpUtils.java
@@ -27,10 +27,12 @@
import static com.android.internal.app.procstats.ProcessStats.ADJ_SCREEN_OFF;
import static com.android.internal.app.procstats.ProcessStats.ADJ_SCREEN_ON;
import static com.android.internal.app.procstats.ProcessStats.STATE_BACKUP;
+import static com.android.internal.app.procstats.ProcessStats.STATE_BOUND_TOP_OR_FGS;
import static com.android.internal.app.procstats.ProcessStats.STATE_CACHED_ACTIVITY;
import static com.android.internal.app.procstats.ProcessStats.STATE_CACHED_ACTIVITY_CLIENT;
import static com.android.internal.app.procstats.ProcessStats.STATE_CACHED_EMPTY;
import static com.android.internal.app.procstats.ProcessStats.STATE_COUNT;
+import static com.android.internal.app.procstats.ProcessStats.STATE_FGS;
import static com.android.internal.app.procstats.ProcessStats.STATE_HEAVY_WEIGHT;
import static com.android.internal.app.procstats.ProcessStats.STATE_HOME;
import static com.android.internal.app.procstats.ProcessStats.STATE_IMPORTANT_BACKGROUND;
@@ -70,6 +72,8 @@
STATE_NAMES = new String[STATE_COUNT];
STATE_NAMES[STATE_PERSISTENT] = "Persist";
STATE_NAMES[STATE_TOP] = "Top";
+ STATE_NAMES[STATE_BOUND_TOP_OR_FGS] = "BTopFgs";
+ STATE_NAMES[STATE_FGS] = "Fgs";
STATE_NAMES[STATE_IMPORTANT_FOREGROUND] = "ImpFg";
STATE_NAMES[STATE_IMPORTANT_BACKGROUND] = "ImpBg";
STATE_NAMES[STATE_BACKUP] = "Backup";
@@ -86,6 +90,9 @@
STATE_LABELS = new String[STATE_COUNT];
STATE_LABELS[STATE_PERSISTENT] = "Persistent";
STATE_LABELS[STATE_TOP] = " Top";
+ STATE_LABELS[STATE_BOUND_TOP_OR_FGS] = "Bnd TopFgs";
+ STATE_LABELS[STATE_FGS] = " Fgs";
+ STATE_LABELS[STATE_IMPORTANT_FOREGROUND] = " Imp Fg";
STATE_LABELS[STATE_IMPORTANT_FOREGROUND] = " Imp Fg";
STATE_LABELS[STATE_IMPORTANT_BACKGROUND] = " Imp Bg";
STATE_LABELS[STATE_BACKUP] = " Backup";
@@ -104,6 +111,8 @@
STATE_NAMES_CSV = new String[STATE_COUNT];
STATE_NAMES_CSV[STATE_PERSISTENT] = "pers";
STATE_NAMES_CSV[STATE_TOP] = "top";
+ STATE_NAMES_CSV[STATE_BOUND_TOP_OR_FGS] = "btopfgs";
+ STATE_NAMES_CSV[STATE_FGS] = "fgs";
STATE_NAMES_CSV[STATE_IMPORTANT_FOREGROUND] = "impfg";
STATE_NAMES_CSV[STATE_IMPORTANT_BACKGROUND] = "impbg";
STATE_NAMES_CSV[STATE_BACKUP] = "backup";
@@ -120,6 +129,8 @@
STATE_TAGS = new String[STATE_COUNT];
STATE_TAGS[STATE_PERSISTENT] = "p";
STATE_TAGS[STATE_TOP] = "t";
+ STATE_TAGS[STATE_BOUND_TOP_OR_FGS] = "d";
+ STATE_TAGS[STATE_FGS] = "g";
STATE_TAGS[STATE_IMPORTANT_FOREGROUND] = "f";
STATE_TAGS[STATE_IMPORTANT_BACKGROUND] = "b";
STATE_TAGS[STATE_BACKUP] = "u";
@@ -136,6 +147,9 @@
STATE_PROTO_ENUMS = new int[STATE_COUNT];
STATE_PROTO_ENUMS[STATE_PERSISTENT] = ProcessStatsEnums.PROCESS_STATE_PERSISTENT;
STATE_PROTO_ENUMS[STATE_TOP] = ProcessStatsEnums.PROCESS_STATE_TOP;
+ STATE_PROTO_ENUMS[STATE_BOUND_TOP_OR_FGS] =
+ ProcessStatsEnums.PROCESS_STATE_BOUND_TOP_OR_FGS;
+ STATE_PROTO_ENUMS[STATE_FGS] = ProcessStatsEnums.PROCESS_STATE_FGS;
STATE_PROTO_ENUMS[STATE_IMPORTANT_FOREGROUND] =
ProcessStatsEnums.PROCESS_STATE_IMPORTANT_FOREGROUND;
STATE_PROTO_ENUMS[STATE_IMPORTANT_BACKGROUND] =
@@ -160,6 +174,10 @@
ProcessStatsEnums.AGGREGATED_PROCESS_STATE_PERSISTENT;
PROCESS_STATS_STATE_TO_AGGREGATED_STATE[STATE_TOP] =
ProcessStatsEnums.AGGREGATED_PROCESS_STATE_TOP;
+ PROCESS_STATS_STATE_TO_AGGREGATED_STATE[STATE_BOUND_TOP_OR_FGS] =
+ ProcessStatsEnums.AGGREGATED_PROCESS_STATE_BOUND_TOP_OR_FGS;
+ PROCESS_STATS_STATE_TO_AGGREGATED_STATE[STATE_FGS] =
+ ProcessStatsEnums.AGGREGATED_PROCESS_STATE_FGS;
PROCESS_STATS_STATE_TO_AGGREGATED_STATE[STATE_IMPORTANT_FOREGROUND] =
ProcessStatsEnums.AGGREGATED_PROCESS_STATE_IMPORTANT_FOREGROUND;
PROCESS_STATS_STATE_TO_AGGREGATED_STATE[STATE_IMPORTANT_BACKGROUND] =
diff --git a/core/java/com/android/internal/app/procstats/ProcessState.java b/core/java/com/android/internal/app/procstats/ProcessState.java
index ab58fc0e..4bced27 100644
--- a/core/java/com/android/internal/app/procstats/ProcessState.java
+++ b/core/java/com/android/internal/app/procstats/ProcessState.java
@@ -28,10 +28,12 @@
import static com.android.internal.app.procstats.ProcessStats.PSS_USS_MAXIMUM;
import static com.android.internal.app.procstats.ProcessStats.PSS_USS_MINIMUM;
import static com.android.internal.app.procstats.ProcessStats.STATE_BACKUP;
+import static com.android.internal.app.procstats.ProcessStats.STATE_BOUND_TOP_OR_FGS;
import static com.android.internal.app.procstats.ProcessStats.STATE_CACHED_ACTIVITY;
import static com.android.internal.app.procstats.ProcessStats.STATE_CACHED_ACTIVITY_CLIENT;
import static com.android.internal.app.procstats.ProcessStats.STATE_CACHED_EMPTY;
import static com.android.internal.app.procstats.ProcessStats.STATE_COUNT;
+import static com.android.internal.app.procstats.ProcessStats.STATE_FGS;
import static com.android.internal.app.procstats.ProcessStats.STATE_HEAVY_WEIGHT;
import static com.android.internal.app.procstats.ProcessStats.STATE_HOME;
import static com.android.internal.app.procstats.ProcessStats.STATE_IMPORTANT_BACKGROUND;
@@ -63,6 +65,8 @@
import android.util.proto.ProtoUtils;
import com.android.internal.app.ProcessMap;
+import com.android.internal.app.procstats.AssociationState.SourceKey;
+import com.android.internal.app.procstats.AssociationState.SourceState;
import com.android.internal.app.procstats.ProcessStats.PackageState;
import com.android.internal.app.procstats.ProcessStats.ProcessStateHolder;
import com.android.internal.app.procstats.ProcessStats.TotalMemoryUseCollection;
@@ -80,9 +84,9 @@
STATE_PERSISTENT, // ActivityManager.PROCESS_STATE_PERSISTENT
STATE_PERSISTENT, // ActivityManager.PROCESS_STATE_PERSISTENT_UI
STATE_TOP, // ActivityManager.PROCESS_STATE_TOP
- STATE_IMPORTANT_FOREGROUND, // ActivityManager.PROCESS_STATE_BOUND_TOP
- STATE_IMPORTANT_FOREGROUND, // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE
- STATE_IMPORTANT_FOREGROUND, // ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
+ STATE_BOUND_TOP_OR_FGS, // ActivityManager.PROCESS_STATE_BOUND_TOP
+ STATE_FGS, // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE
+ STATE_BOUND_TOP_OR_FGS, // ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
STATE_IMPORTANT_FOREGROUND, // ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
STATE_IMPORTANT_BACKGROUND, // ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
STATE_IMPORTANT_BACKGROUND, // ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND
@@ -163,6 +167,11 @@
private long mTmpTotalTime;
/**
+ * The combined source states which has or had an association with this process.
+ */
+ ArrayMap<SourceKey, SourceState> mCommonSources;
+
+ /**
* Create a new top-level process state, for the initial case where there is only
* a single package running in a process. The initial state is not running.
*/
@@ -267,6 +276,21 @@
addCachedKill(other.mNumCachedKill, other.mMinCachedKillPss,
other.mAvgCachedKillPss, other.mMaxCachedKillPss);
}
+ if (other.mCommonSources != null) {
+ if (mCommonSources == null) {
+ mCommonSources = new ArrayMap<>();
+ }
+ int size = other.mCommonSources.size();
+ for (int i = 0; i < size; i++) {
+ final SourceKey key = other.mCommonSources.keyAt(i);
+ SourceState state = mCommonSources.get(key);
+ if (state == null) {
+ state = new SourceState(mStats, null, this, key);
+ mCommonSources.put(key, state);
+ }
+ state.add(other.mCommonSources.valueAt(i));
+ }
+ }
}
public void resetSafely(long now) {
@@ -278,6 +302,17 @@
mNumExcessiveCpu = 0;
mNumCachedKill = 0;
mMinCachedKillPss = mAvgCachedKillPss = mMaxCachedKillPss = 0;
+ // Reset the combine source state.
+ if (mCommonSources != null) {
+ for (int ip = mCommonSources.size() - 1; ip >= 0; ip--) {
+ final SourceState state = mCommonSources.valueAt(ip);
+ if (state.isInUse()) {
+ state.resetSafely(now);
+ } else {
+ mCommonSources.removeAt(ip);
+ }
+ }
+ }
}
public void makeDead() {
@@ -308,9 +343,18 @@
out.writeLong(mAvgCachedKillPss);
out.writeLong(mMaxCachedKillPss);
}
+ // The combined source state of all associations.
+ final int numOfSources = mCommonSources != null ? mCommonSources.size() : 0;
+ out.writeInt(numOfSources);
+ for (int i = 0; i < numOfSources; i++) {
+ final SourceKey key = mCommonSources.keyAt(i);
+ final SourceState src = mCommonSources.valueAt(i);
+ key.writeToParcel(mStats, out);
+ src.writeToParcel(out, 0);
+ }
}
- public boolean readFromParcel(Parcel in, boolean fully) {
+ boolean readFromParcel(Parcel in, int version, boolean fully) {
boolean multiPackage = in.readInt() != 0;
if (fully) {
mMultiPackage = multiPackage;
@@ -337,6 +381,19 @@
} else {
mMinCachedKillPss = mAvgCachedKillPss = mMaxCachedKillPss = 0;
}
+
+ // The combined source state of all associations.
+ final int numOfSources = in.readInt();
+ if (numOfSources > 0) {
+ mCommonSources = new ArrayMap<>(numOfSources);
+ for (int i = 0; i < numOfSources; i++) {
+ final SourceKey key = new SourceKey(mStats, in, version);
+ final SourceState src = new SourceState(mStats, null, this, key);
+ src.readFromParcel(in);
+ mCommonSources.put(key, src);
+ }
+ }
+
return true;
}
@@ -433,6 +490,12 @@
mTotalRunningStartTime = now;
}
mStartTime = now;
+ if (mCommonSources != null) {
+ for (int ip = mCommonSources.size() - 1; ip >= 0; ip--) {
+ final SourceState src = mCommonSources.valueAt(ip);
+ src.commitStateTime(now);
+ }
+ }
}
public void incActiveServices(String serviceName) {
@@ -722,6 +785,18 @@
return mPssTable.getValueForId((byte)state, PSS_RSS_MAXIMUM);
}
+ SourceState getOrCreateSourceState(SourceKey key) {
+ if (mCommonSources == null) {
+ mCommonSources = new ArrayMap<>();
+ }
+ SourceState state = mCommonSources.get(key);
+ if (state == null) {
+ state = new SourceState(mStats, null, this, key);
+ mCommonSources.put(key, state);
+ }
+ return state;
+ }
+
/**
* Sums up the PSS data and adds it to 'data'.
*
@@ -846,6 +921,12 @@
screenStates, memStates, new int[] { STATE_PERSISTENT }, now, totalTime, true);
dumpProcessSummaryDetails(pw, prefix, DumpUtils.STATE_LABELS[STATE_TOP],
screenStates, memStates, new int[] {STATE_TOP}, now, totalTime, true);
+ dumpProcessSummaryDetails(pw, prefix, DumpUtils.STATE_LABELS[STATE_BOUND_TOP_OR_FGS],
+ screenStates, memStates, new int[] { STATE_BOUND_TOP_OR_FGS}, now, totalTime,
+ true);
+ dumpProcessSummaryDetails(pw, prefix, DumpUtils.STATE_LABELS[STATE_FGS],
+ screenStates, memStates, new int[] { STATE_FGS}, now, totalTime,
+ true);
dumpProcessSummaryDetails(pw, prefix, DumpUtils.STATE_LABELS[STATE_IMPORTANT_FOREGROUND],
screenStates, memStates, new int[] { STATE_IMPORTANT_FOREGROUND }, now, totalTime,
true);
@@ -1038,7 +1119,8 @@
}
}
- public void dumpInternalLocked(PrintWriter pw, String prefix, boolean dumpAll) {
+ void dumpInternalLocked(PrintWriter pw, String prefix, String reqPackage,
+ long totalTime, long now, boolean dumpAll) {
if (dumpAll) {
pw.print(prefix); pw.print("myID=");
pw.print(Integer.toHexString(System.identityHashCode(this)));
@@ -1053,6 +1135,13 @@
pw.print("/"); pw.print(mCommonProcess.mUid);
pw.print(" pkg="); pw.println(mCommonProcess.mPackage);
}
+ if (mCommonSources != null) {
+ pw.print(prefix); pw.println("Aggregated Association Sources:");
+ AssociationState.dumpSources(
+ pw, prefix + " ", prefix + " ", prefix + " ",
+ AssociationState.createSortedAssociations(now, totalTime, mCommonSources),
+ now, totalTime, reqPackage, true, dumpAll);
+ }
}
if (mActive) {
pw.print(prefix); pw.print("mActive="); pw.println(mActive);
@@ -1559,7 +1648,7 @@
}
mStats.dumpFilteredAssociationStatesProtoForProc(proto, ProcessStatsProto.ASSOCS,
- now, this, procToPkgMap, uidToPkgMap);
+ now, this, uidToPkgMap);
proto.end(token);
}
}
diff --git a/core/java/com/android/internal/app/procstats/ProcessStats.java b/core/java/com/android/internal/app/procstats/ProcessStats.java
index 11e55b8..fd16662 100644
--- a/core/java/com/android/internal/app/procstats/ProcessStats.java
+++ b/core/java/com/android/internal/app/procstats/ProcessStats.java
@@ -29,7 +29,6 @@
import android.service.procstats.ProcessStatsAvailablePagesProto;
import android.service.procstats.ProcessStatsPackageProto;
import android.service.procstats.ProcessStatsSectionProto;
-import android.text.TextUtils;
import android.text.format.DateFormat;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -79,18 +78,20 @@
public static final int STATE_NOTHING = -1;
public static final int STATE_PERSISTENT = 0;
public static final int STATE_TOP = 1;
- public static final int STATE_IMPORTANT_FOREGROUND = 2;
- public static final int STATE_IMPORTANT_BACKGROUND = 3;
- public static final int STATE_BACKUP = 4;
- public static final int STATE_SERVICE = 5;
- public static final int STATE_SERVICE_RESTARTING = 6;
- public static final int STATE_RECEIVER = 7;
- public static final int STATE_HEAVY_WEIGHT = 8;
- public static final int STATE_HOME = 9;
- public static final int STATE_LAST_ACTIVITY = 10;
- public static final int STATE_CACHED_ACTIVITY = 11;
- public static final int STATE_CACHED_ACTIVITY_CLIENT = 12;
- public static final int STATE_CACHED_EMPTY = 13;
+ public static final int STATE_BOUND_TOP_OR_FGS = 2;
+ public static final int STATE_FGS = 3;
+ public static final int STATE_IMPORTANT_FOREGROUND = 4;
+ public static final int STATE_IMPORTANT_BACKGROUND = 5;
+ public static final int STATE_BACKUP = 6;
+ public static final int STATE_SERVICE = 7;
+ public static final int STATE_SERVICE_RESTARTING = 8;
+ public static final int STATE_RECEIVER = 9;
+ public static final int STATE_HEAVY_WEIGHT = 10;
+ public static final int STATE_HOME = 11;
+ public static final int STATE_LAST_ACTIVITY = 12;
+ public static final int STATE_CACHED_ACTIVITY = 13;
+ public static final int STATE_CACHED_ACTIVITY_CLIENT = 14;
+ public static final int STATE_CACHED_EMPTY = 15;
public static final int STATE_COUNT = STATE_CACHED_EMPTY+1;
public static final int PSS_SAMPLE_COUNT = 0;
@@ -150,8 +151,8 @@
public static final int[] ALL_SCREEN_ADJ = new int[] { ADJ_SCREEN_OFF, ADJ_SCREEN_ON };
public static final int[] NON_CACHED_PROC_STATES = new int[] {
- STATE_PERSISTENT, STATE_TOP, STATE_IMPORTANT_FOREGROUND,
- STATE_IMPORTANT_BACKGROUND, STATE_BACKUP,
+ STATE_PERSISTENT, STATE_TOP, STATE_BOUND_TOP_OR_FGS, STATE_FGS,
+ STATE_IMPORTANT_FOREGROUND, STATE_IMPORTANT_BACKGROUND, STATE_BACKUP,
STATE_SERVICE, STATE_SERVICE_RESTARTING, STATE_RECEIVER, STATE_HEAVY_WEIGHT
};
@@ -161,7 +162,8 @@
};
public static final int[] ALL_PROC_STATES = new int[] { STATE_PERSISTENT,
- STATE_TOP, STATE_IMPORTANT_FOREGROUND, STATE_IMPORTANT_BACKGROUND, STATE_BACKUP,
+ STATE_TOP, STATE_BOUND_TOP_OR_FGS, STATE_FGS, STATE_IMPORTANT_FOREGROUND,
+ STATE_IMPORTANT_BACKGROUND, STATE_BACKUP,
STATE_SERVICE, STATE_SERVICE_RESTARTING, STATE_RECEIVER,
STATE_HEAVY_WEIGHT, STATE_HOME, STATE_LAST_ACTIVITY, STATE_CACHED_ACTIVITY,
STATE_CACHED_ACTIVITY_CLIENT, STATE_CACHED_EMPTY
@@ -187,7 +189,7 @@
{"proc", "pkg-proc", "pkg-svc", "pkg-asc", "pkg-all", "all"};
// Current version of the parcel format.
- private static final int PARCEL_VERSION = 38;
+ private static final int PARCEL_VERSION = 40;
// In-memory Parcel magic number, used to detect attempts to unmarshall bad data
private static final int MAGIC = 0x50535454;
@@ -1113,12 +1115,12 @@
final long vers = in.readLong();
ProcessState proc = hadData ? mProcesses.get(procName, uid) : null;
if (proc != null) {
- if (!proc.readFromParcel(in, false)) {
+ if (!proc.readFromParcel(in, version, false)) {
return;
}
} else {
proc = new ProcessState(this, pkgName, uid, vers, procName);
- if (!proc.readFromParcel(in, true)) {
+ if (!proc.readFromParcel(in, version, true)) {
return;
}
}
@@ -1198,13 +1200,13 @@
// they will find and use it from the global procs.
ProcessState proc = hadData ? pkgState.mProcesses.get(procName) : null;
if (proc != null) {
- if (!proc.readFromParcel(in, false)) {
+ if (!proc.readFromParcel(in, version, false)) {
return;
}
} else {
proc = new ProcessState(commonProc, pkgName, uid, vers, procName,
0);
- if (!proc.readFromParcel(in, true)) {
+ if (!proc.readFromParcel(in, version, true)) {
return;
}
}
@@ -1439,16 +1441,15 @@
final int NUM = mTrackingAssociations.size();
for (int i = NUM - 1; i >= 0; i--) {
final AssociationState.SourceState act = mTrackingAssociations.get(i);
- if (act.mProcStateSeq != curSeq || act.mProcState >= ProcessStats.STATE_HOME) {
- // If this association did not get touched the last time we computed
- // process states, or its state ended up down in cached, then we no
- // longer have a reason to track it at all.
- act.stopActive(now);
- act.mInTrackingList = false;
- act.mProcState = ProcessStats.STATE_NOTHING;
+ if (act.stopActiveIfNecessary(curSeq, now)) {
mTrackingAssociations.remove(i);
} else {
- final ProcessState proc = act.getAssociationState().getProcess();
+ final AssociationState asc = act.getAssociationState();
+ if (asc == null) {
+ Slog.wtf(TAG, act.toString() + " shouldn't be in the tracking list.");
+ continue;
+ }
+ final ProcessState proc = asc.getProcess();
if (proc != null) {
final int procState = proc.getCombinedState() % STATE_COUNT;
if (act.mProcState == procState) {
@@ -1476,7 +1477,7 @@
} else {
// Don't need rate limiting on it.
Slog.wtf(TAG, "Tracking association without process: " + act
- + " in " + act.getAssociationState());
+ + " in " + asc);
}
}
}
@@ -1640,7 +1641,8 @@
ALL_PROC_STATES, now);
proc.dumpPss(pw, " ", ALL_SCREEN_ADJ, ALL_MEM_ADJ,
ALL_PROC_STATES, now);
- proc.dumpInternalLocked(pw, " ", dumpAll);
+ proc.dumpInternalLocked(pw, " ", reqPackage,
+ totalTime, now, dumpAll);
}
} else {
ArrayList<ProcessState> procs = new ArrayList<ProcessState>();
@@ -1696,7 +1698,8 @@
}
final AssociationDumpContainer cont =
new AssociationDumpContainer(asc);
- cont.mSources = asc.createSortedAssociations(now, totalTime);
+ cont.mSources = AssociationState
+ .createSortedAssociations(now, totalTime, asc.mSources);
cont.mTotalTime = asc.getTotalDuration(now);
cont.mActiveTime = asc.getActiveDuration(now);
associations.add(cont);
@@ -1777,7 +1780,7 @@
proc.dumpProcessState(pw, " ", ALL_SCREEN_ADJ, ALL_MEM_ADJ,
ALL_PROC_STATES, now);
proc.dumpPss(pw, " ", ALL_SCREEN_ADJ, ALL_MEM_ADJ, ALL_PROC_STATES, now);
- proc.dumpInternalLocked(pw, " ", dumpAll);
+ proc.dumpInternalLocked(pw, " ", reqPackage, totalTime, now, dumpAll);
}
}
pw.print(" Total procs: "); pw.print(numShownProcs);
@@ -1792,6 +1795,10 @@
for (int i = 0; i < mTrackingAssociations.size(); i++) {
final AssociationState.SourceState src = mTrackingAssociations.get(i);
final AssociationState asc = src.getAssociationState();
+ if (asc == null) {
+ Slog.wtf(TAG, src.toString() + " shouldn't be in the tracking list.");
+ continue;
+ }
pw.print(" #");
pw.print(i);
pw.print(": ");
@@ -2353,85 +2360,47 @@
* @param fieldId The proto output field ID
* @param now The timestamp when the dump was initiated.
* @param procState The target process where its association states should be dumped.
- * @param proc2Pkg The map between process to packages running within it.
* @param uidToPkgMap The map between UID to packages with this UID
*/
public void dumpFilteredAssociationStatesProtoForProc(ProtoOutputStream proto,
long fieldId, long now, ProcessState procState,
- final ProcessMap<ArraySet<PackageState>> proc2Pkg,
final SparseArray<ArraySet<String>> uidToPkgMap) {
if (procState.isMultiPackage() && procState.getCommonProcess() != procState) {
// It's a per-package process state, don't bother to write into statsd
return;
}
- ArrayMap<SourceKey, long[]> assocVals = new ArrayMap<>();
- final String procName = procState.getName();
- final int procUid = procState.getUid();
- final long procVersion = procState.getVersion();
- final ArraySet<PackageState> packages = proc2Pkg.get(procName, procUid);
- if (packages == null || packages.isEmpty()) {
- // Shouldn't happen
- return;
- }
- for (int i = packages.size() - 1; i >= 0; i--) {
- final PackageState pkgState = packages.valueAt(i);
- final ArrayMap<String, AssociationState> associations = pkgState.mAssociations;
- for (int j = associations.size() - 1; j >= 0; j--) {
- final AssociationState assoc = associations.valueAt(j);
- // Make sure this association is really about this process
- if (!TextUtils.equals(assoc.getProcessName(), procName)) {
- continue;
- }
- final ArrayMap<SourceKey, SourceState> sources = assoc.mSources;
- for (int k = sources.size() - 1; k >= 0; k--) {
- final SourceKey key = sources.keyAt(k);
- final SourceState state = sources.valueAt(k);
- long[] vals = assocVals.get(key);
- if (vals == null) {
- vals = new long[2];
- assocVals.put(key, vals);
- }
- vals[0] += state.mDuration;
- vals[1] += state.mCount;
- if (state.mNesting > 0) {
- vals[0] += now - state.mStartUptime;
- }
- }
- }
- }
- final IProcessStats procStatsService = IProcessStats.Stub.asInterface(
- ServiceManager.getService(SERVICE_NAME));
- if (procStatsService != null) {
- try {
- final long minimum = procStatsService.getMinAssociationDumpDuration();
- if (minimum > 0) {
- // Now filter out unnecessary ones.
- for (int i = assocVals.size() - 1; i >= 0; i--) {
- final long[] vals = assocVals.valueAt(i);
- if (vals[0] < minimum) {
- assocVals.removeAt(i);
+ final ArrayMap<SourceKey, SourceState> sources = procState.mCommonSources;
+ if (sources != null && !sources.isEmpty()) {
+ final IProcessStats procStatsService = IProcessStats.Stub.asInterface(
+ ServiceManager.getService(SERVICE_NAME));
+ if (procStatsService != null) {
+ try {
+ final long minimum = procStatsService.getMinAssociationDumpDuration();
+ for (int i = sources.size() - 1; i >= 0; i--) {
+ final SourceState src = sources.valueAt(i);
+ long duration = src.mDuration;
+ if (src.mNesting > 0) {
+ duration += now - src.mStartUptime;
}
+ if (duration < minimum) {
+ continue;
+ }
+ final SourceKey key = sources.keyAt(i);
+ final long token = proto.start(fieldId);
+ final int idx = uidToPkgMap.indexOfKey(key.mUid);
+ ProcessState.writeCompressedProcessName(proto,
+ ProcessStatsAssociationProto.ASSOC_PROCESS_NAME,
+ key.mProcess, key.mPackage,
+ idx >= 0 && uidToPkgMap.valueAt(idx).size() > 1);
+ proto.write(ProcessStatsAssociationProto.ASSOC_UID, key.mUid);
+ proto.write(ProcessStatsAssociationProto.TOTAL_COUNT, src.mCount);
+ proto.write(ProcessStatsAssociationProto.TOTAL_DURATION_SECS,
+ (int) (duration / 1000));
+ proto.end(token);
}
+ } catch (RemoteException e) {
+ // ignore.
}
- } catch (RemoteException e) {
- // ignore.
- }
- }
- if (!assocVals.isEmpty()) {
- for (int i = assocVals.size() - 1; i >= 0; i--) {
- final SourceKey key = assocVals.keyAt(i);
- final long[] vals = assocVals.valueAt(i);
- final long token = proto.start(fieldId);
- final int idx = uidToPkgMap.indexOfKey(key.mUid);
- ProcessState.writeCompressedProcessName(proto,
- ProcessStatsAssociationProto.ASSOC_PROCESS_NAME,
- key.mProcess, key.mPackage,
- idx >= 0 && uidToPkgMap.valueAt(idx).size() > 1);
- proto.write(ProcessStatsAssociationProto.ASSOC_UID, key.mUid);
- proto.write(ProcessStatsAssociationProto.TOTAL_COUNT, (int) vals[1]);
- proto.write(ProcessStatsAssociationProto.TOTAL_DURATION_SECS,
- (int) (vals[0] / 1000));
- proto.end(token);
}
}
}
diff --git a/core/java/com/android/internal/inputmethod/InputMethodDebug.java b/core/java/com/android/internal/inputmethod/InputMethodDebug.java
index d026ecd..a00b993 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodDebug.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodDebug.java
@@ -234,6 +234,8 @@
return "SHOW_TOGGLE_SOFT_INPUT";
case SoftInputShowHideReason.HIDE_TOGGLE_SOFT_INPUT:
return "HIDE_TOGGLE_SOFT_INPUT";
+ case SoftInputShowHideReason.SHOW_SOFT_INPUT_BY_INSETS_API:
+ return "SHOW_SOFT_INPUT_BY_INSETS_API";
default:
return "Unknown=" + reason;
}
diff --git a/core/java/com/android/internal/inputmethod/SoftInputShowHideReason.java b/core/java/com/android/internal/inputmethod/SoftInputShowHideReason.java
index 755bd5e..e3713a3 100644
--- a/core/java/com/android/internal/inputmethod/SoftInputShowHideReason.java
+++ b/core/java/com/android/internal/inputmethod/SoftInputShowHideReason.java
@@ -52,7 +52,8 @@
SoftInputShowHideReason.HIDE_REMOVE_CLIENT,
SoftInputShowHideReason.SHOW_RESTORE_IME_VISIBILITY,
SoftInputShowHideReason.SHOW_TOGGLE_SOFT_INPUT,
- SoftInputShowHideReason.HIDE_TOGGLE_SOFT_INPUT})
+ SoftInputShowHideReason.HIDE_TOGGLE_SOFT_INPUT,
+ SoftInputShowHideReason.SHOW_SOFT_INPUT_BY_INSETS_API})
public @interface SoftInputShowHideReason {
/** Show soft input by {@link android.view.inputmethod.InputMethodManager#showSoftInput}. */
int SHOW_SOFT_INPUT = 0;
@@ -188,4 +189,10 @@
* {@link android.view.inputmethod.InputMethodManager#toggleSoftInput(int, int)};
*/
int HIDE_TOGGLE_SOFT_INPUT = 24;
+
+ /**
+ * Show soft input by
+ * {@link android.view.InsetsController#show(int)};
+ */
+ int SHOW_SOFT_INPUT_BY_INSETS_API = 25;
}
diff --git a/core/jni/android_view_InputEventSender.cpp b/core/jni/android_view_InputEventSender.cpp
index fd1b9981..45e3d1b 100644
--- a/core/jni/android_view_InputEventSender.cpp
+++ b/core/jni/android_view_InputEventSender.cpp
@@ -155,7 +155,8 @@
event->getYPrecision(),
event->getRawXCursorPosition(),
event->getRawYCursorPosition(),
- event->getDownTime(),
+ event->getDisplaySize().x,
+ event->getDisplaySize().y, event->getDownTime(),
event->getHistoricalEventTime(i),
event->getPointerCount(),
event->getPointerProperties(),
diff --git a/core/jni/android_view_MotionEvent.cpp b/core/jni/android_view_MotionEvent.cpp
index 832c066..5acbd98 100644
--- a/core/jni/android_view_MotionEvent.cpp
+++ b/core/jni/android_view_MotionEvent.cpp
@@ -378,7 +378,8 @@
flags, edgeFlags, metaState, buttonState,
static_cast<MotionClassification>(classification), transform, xPrecision,
yPrecision, AMOTION_EVENT_INVALID_CURSOR_POSITION,
- AMOTION_EVENT_INVALID_CURSOR_POSITION, downTimeNanos, eventTimeNanos,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_DISPLAY_SIZE,
+ AMOTION_EVENT_INVALID_DISPLAY_SIZE, downTimeNanos, eventTimeNanos,
pointerCount, pointerProperties, rawPointerCoords);
return reinterpret_cast<jlong>(event.release());
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 8b70966..fee82ba 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -825,7 +825,7 @@
PrepareDir(user_source, 0710, user_id ? AID_ROOT : AID_SHELL,
multiuser_get_uid(user_id, AID_EVERYBODY), fail_fn);
- bool isAppDataIsolationEnabled = GetBoolProperty(kVoldAppDataIsolation, false);
+ bool isAppDataIsolationEnabled = GetBoolProperty(kVoldAppDataIsolation, true);
if (mount_mode == MOUNT_EXTERNAL_PASS_THROUGH) {
const std::string pass_through_source = StringPrintf("/mnt/pass_through/%d", user_id);
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 210c5bc..e9c5269 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -2287,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Programhandelsmerkprent"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Gaan toeganginstellings na"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> kan jou skerm sien en beheer. Tik om na te gaan."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index d5d06633..3ea2d0c 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -2085,17 +2085,12 @@
<string name="notification_feedback_indicator_silenced" msgid="3799442124723177262">"ይህ ማሳወቂያ ወደ ዝምታ ዝቅ ብሏል። ግብረመልስ ለመስጠት መታ ያድርጉ።"</string>
<string name="notification_feedback_indicator_promoted" msgid="9030204303764698640">"ይህ ማሳወቂያ ከፍተኛ ደረጃ ተሰጥቶታል። ግብረመልስ ለመስጠት መታ ያድርጉ።"</string>
<string name="notification_feedback_indicator_demoted" msgid="8880309924296450875">"ይህ ማሳወቂያ ዝቅተኛ ደረጃ ተሰጥቶታል። ግብረመልስ ለመስጠት መታ ያድርጉ።"</string>
- <!-- no translation found for nas_upgrade_notification_title (8436359459300146555) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_content (5157550369837103337) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_enable_action (3046406808378726874) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_disable_action (3794833210043497982) -->
- <skip />
+ <string name="nas_upgrade_notification_title" msgid="8436359459300146555">"የተሻሻሉ ማሳወቂያዎች"</string>
+ <string name="nas_upgrade_notification_content" msgid="5157550369837103337">"የተጠቆሙ እርምጃዎች እና ምላሾች አሁን በተሻሻሉ ማሳወቂያዎች ቀርበዋል። የAndroid አስማሚ ማሳወቂያዎች ከእንግዲህ አይደገፉም።"</string>
+ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"እሺ"</string>
+ <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"አጥፋ"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"የበለጠ ለመረዳት"</string>
- <!-- no translation found for nas_upgrade_notification_learn_more_content (2353549817159426430) -->
- <skip />
+ <string name="nas_upgrade_notification_learn_more_content" msgid="2353549817159426430">"የተሻሻሉ ማሳወቂያዎች በAndroid 12 ውስጥ Android ራስ-አስማሚ ማሳወቂያዎችን ተክተዋል። ይህ ባህሪ የተጠቆሙ እርምጃዎችን እና ምላሾችን ያሳያል እንዲሁም ማሳወቂያዎችዎን ያደራጃል።\n\nየተሻሻሉ ማሳወቂያዎች እንደ የእውቂያ ስሞች እና መልዕክቶች ያሉ የግል መረጃዎችን ጨምሮ የማሳወቂያ ይዘቶችን መድረስ ይችላሉ። ይህ ባህሪ እንደ የስልክ ጥሪዎችን መመለስ እና አትረብሽን መቆጣጠርን ያሉ ማሳወቂያዎችን ማሰናበት ወይም ምላሽ መስጠት ይችላል።"</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"የዕለት ተዕለት ሁነታ መረጃ ማሳወቂያዎች"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"ባትሪ ከተለመደው ኃይል መሙላት በፊት ሊያልቅ ይችላል"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"የባትሪ ቆጣቢ የባትሪ ዕድሜን ለማራዘም ገብሯል።"</string>
@@ -2292,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"የመተግበሪያ የምርት ስም ምስል"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"የመዳረሻ ቅንብሮችን ይፈትሹ"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> ማያ ገጽዎን ማየት እና መቆጣጠር ይችላል። ለመገምገም መታ ያድርጉ።"</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 1b7e8fd..cf3968d 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -2217,17 +2217,12 @@
<string name="notification_feedback_indicator_silenced" msgid="3799442124723177262">"تم خفض ترتيب هذا الإشعار إلى الوضع \"صامت\". انقر لإرسال ملاحظات وآراء."</string>
<string name="notification_feedback_indicator_promoted" msgid="9030204303764698640">"تمت زيادة ترتيب هذا الإشعار. انقر لإرسال ملاحظات وآراء."</string>
<string name="notification_feedback_indicator_demoted" msgid="8880309924296450875">"تم خفض ترتيب هذا الإشعار. انقر لإرسال ملاحظات وآراء."</string>
- <!-- no translation found for nas_upgrade_notification_title (8436359459300146555) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_content (5157550369837103337) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_enable_action (3046406808378726874) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_disable_action (3794833210043497982) -->
- <skip />
+ <string name="nas_upgrade_notification_title" msgid="8436359459300146555">"الإشعارات المحسّنة"</string>
+ <string name="nas_upgrade_notification_content" msgid="5157550369837103337">"يتم الآن توفير الإجراءات والردود المقترحة من خلال الإشعارات المحسّنة. ولم تعد الإشعارات التكيُّفية لنظام التشغيل Android متاحة."</string>
+ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"حسنًا"</string>
+ <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"إيقاف"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"مزيد من المعلومات"</string>
- <!-- no translation found for nas_upgrade_notification_learn_more_content (2353549817159426430) -->
- <skip />
+ <string name="nas_upgrade_notification_learn_more_content" msgid="2353549817159426430">"تم إبدال الإشعارات المحسّنة بالإشعارات التكيُّفية لنظام التشغيل Android في الإصدار 12 منه. تعرض هذه الميزة إجراءات وردودًا مقترحة وتنظِّم الإشعارات.\n\nيمكن للإشعارات المحسّنة الوصول إلى محتوى الإشعارات، بما في المعلومات الشخصية، مثلاً أسماء جهات الاتصال والرسائل. يمكن لهذه الميزة أيضًا إغلاق الإشعارات أو الاستجابة لها، مثلاً الردّ على مكالمات الهاتف والتحكّم في ميزة \"عدم الإزعاج\"."</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"إشعار معلومات \"وضع سلسلة الإجراءات\""</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"قد تنفد طاقة البطارية قبل الشحن المعتاد"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"تم تفعيل \"توفير شحن البطارية\" لإطالة عمرها."</string>
@@ -2428,4 +2423,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"الصورة الذهنية للعلامة التجارية للتطبيق"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"التحقّق من إعدادات الوصول"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"يمكن لخدمة <xliff:g id="SERVICE_NAME">%s</xliff:g> الاطّلاع على شاشتك والتحكّم فيها. انقر لمراجعة الإعدادات."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index 350e981..182fddc 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -1820,8 +1820,7 @@
<string name="mediasize_japanese_kahu" msgid="7290232592648122042">"Kahu"</string>
<string name="mediasize_japanese_kaku2" msgid="7477551750461028312">"Kaku2"</string>
<string name="mediasize_japanese_you4" msgid="5552111912684384833">"You4"</string>
- <!-- no translation found for mediasize_japanese_l (1326765321473431817) -->
- <skip />
+ <string name="mediasize_japanese_l" msgid="1326765321473431817">"L"</string>
<string name="mediasize_unknown_portrait" msgid="3817016220446495613">"অজ্ঞাত প\'ৰ্ট্ৰেইট"</string>
<string name="mediasize_unknown_landscape" msgid="1584741567225095325">"অজ্ঞাত লেণ্ডস্কেইপ"</string>
<string name="write_fail_reason_cancelled" msgid="2344081488493969190">"বাতিল কৰা হ’ল"</string>
@@ -1865,10 +1864,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 (750683025714899363) -->
- <skip />
- <!-- no translation found for battery_saver_description (5693741424234005958) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="750683025714899363">"বেটাৰী সঞ্চয়কাৰীয়ে গাঢ় ৰঙৰ থীম অন কৰে আৰু নেপথ্যৰ কাৰ্যকলাপ, কিছুমান ভিজুৱেল ইফেক্ট আৰু নিৰ্দিষ্ট কিছুমান সুবিধা সীমিত অথবা অফ কৰে।\n\n"<annotation id="url">"অধিক জানক"</annotation></string>
+ <string name="battery_saver_description" msgid="5693741424234005958">"বেটাৰী সঞ্চয়কাৰীয়ে গাঢ় ৰঙৰ থীম অন কৰে আৰু নেপথ্যৰ কাৰ্যকলাপ, কিছুমান ভিজুৱেল ইফেক্ট আৰু নিৰ্দিষ্ট কিছুমান সুবিধা সীমিত অথবা অফ কৰে।"</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>
@@ -2088,17 +2085,12 @@
<string name="notification_feedback_indicator_silenced" msgid="3799442124723177262">"এই জাননীটোৰ গুৰুত্ব নীৰৱলৈ হ্ৰাস কৰা হৈছে। মতামত দিবলৈ টিপক।"</string>
<string name="notification_feedback_indicator_promoted" msgid="9030204303764698640">"এই জাননীটোৰ স্থান ওপৰলৈ কৰা হৈছে। মতামত দিবলৈ টিপক।"</string>
<string name="notification_feedback_indicator_demoted" msgid="8880309924296450875">"এই জাননীটোৰ স্থান তললৈ কৰা হৈছে। মতামত দিবলৈ টিপক।"</string>
- <!-- no translation found for nas_upgrade_notification_title (8436359459300146555) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_content (5157550369837103337) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_enable_action (3046406808378726874) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_disable_action (3794833210043497982) -->
- <skip />
+ <string name="nas_upgrade_notification_title" msgid="8436359459300146555">"উন্নত জাননী"</string>
+ <string name="nas_upgrade_notification_content" msgid="5157550369837103337">"এতিয়া উন্নত জাননীয়ে পৰামৰ্শ দিয়া কাৰ্য আৰু প্ৰত্যুত্তৰ প্ৰদান কৰে। Androidৰ অভিযোজিত জাননী আৰু সমৰ্থিত নহয়।"</string>
+ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"ঠিক আছে"</string>
+ <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"অফ কৰক"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"অধিক জানক"</string>
- <!-- no translation found for nas_upgrade_notification_learn_more_content (2353549817159426430) -->
- <skip />
+ <string name="nas_upgrade_notification_learn_more_content" msgid="2353549817159426430">"Android 12ত Androidৰ অভিযোজিত জাননীক উন্নত জাননীৰ দ্বাৰা সলনি কৰা হৈছে। এই সুবিধাটোৱে পৰামৰ্শ দিয়া কাৰ্য আৰু প্ৰত্যুত্তৰ দেখুৱায় আৰু আপোনাৰ জাননীসমূহ শৃংখলাবদ্ধ কৰে।\n\nউন্নত জাননীয়ে সম্পৰ্কৰ নাম আৰু বাৰ্তাৰ দৰে ব্যক্তিগত তথ্যকে ধৰি জাননীৰ সমল এক্সেছ কৰিব পাৰে। এই সুবিধাটোৱে জাননী অগ্ৰাহ্য কৰিব অথবা জাননীৰ প্ৰতি সঁহাৰি জনাবও পাৰে, যেনে ফ’ন কলৰ উত্তৰ দিয়া আৰু অসুবিধা নিদিব সুবিধাটো নিয়ন্ত্ৰণ কৰা আদি।"</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"ৰুটিন ম’ডৰ তথ্য জাননী"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"চ্চাৰ্জ কৰাৰ সচৰাচৰ সময়ৰ আগতেই বেটাৰি শেষ হ’ব পাৰে"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"বেটাৰিৰ খৰচ কমাবলৈ বেটাৰি সঞ্চয়কাৰী অন কৰা হৈছে"</string>
@@ -2295,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"এপ্লিকেশ্বনৰ ব্ৰেণ্ডৰ প্ৰতিচ্ছবি"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"এক্সেছৰ ছেটিং পৰীক্ষা কৰক"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g>এ আপোনাৰ স্ক্ৰীনখন চাব আৰু পৰিচালনা কৰিব পাৰে। পৰ্যালোচনা কৰিবলৈ টিপক।"</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index 1bdc646..12daa99 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -2085,17 +2085,12 @@
<string name="notification_feedback_indicator_silenced" msgid="3799442124723177262">"Bu bildiriş Səssiz rejimə keçirilib. Rəy bildirmək üçün toxunun."</string>
<string name="notification_feedback_indicator_promoted" msgid="9030204303764698640">"Bu bildiriş yuxarı sıraya keçirilib. Rəy bildirmək üçün toxunun."</string>
<string name="notification_feedback_indicator_demoted" msgid="8880309924296450875">"Bu bildiriş aşağı sıraya keçirilib. Rəy bildirmək üçün toxunun."</string>
- <!-- no translation found for nas_upgrade_notification_title (8436359459300146555) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_content (5157550369837103337) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_enable_action (3046406808378726874) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_disable_action (3794833210043497982) -->
- <skip />
+ <string name="nas_upgrade_notification_title" msgid="8436359459300146555">"Genişləndirilmiş bildirişlər"</string>
+ <string name="nas_upgrade_notification_content" msgid="5157550369837103337">"Təklif olunan əməliyyatlar və cavablar artıq genişləndirilmiş bildirişlər tərəfindən təmin olunur. Android Adaptiv Bildirişləri artıq dəstəklənmir."</string>
+ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"OK"</string>
+ <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"Deaktiv edin"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"Ətraflı məlumat"</string>
- <!-- no translation found for nas_upgrade_notification_learn_more_content (2353549817159426430) -->
- <skip />
+ <string name="nas_upgrade_notification_learn_more_content" msgid="2353549817159426430">"Genişləndirilmiş bildirişlər Android 12-də Android Adaptiv Bildirişləri əvəz etdi. Bu funksiya təklif olunan əməliyyatları və cavabları göstərir və bildirişlərinizi təşkil edir.\n\nGenişləndirilmiş bildirişlər, kontakt adları və mesajlar kimi şəxsi məlumatlar daxil olmaqla bütün bildiriş məzmununa giriş edə bilər. Bu funksiya telefon zənglərinə cavab vermək və Narahat Etməyin rejimini idarə etmək kimi bildirişləri qapada və ya cavablandıra bilər."</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Rejim üçün məlumat bildirişi"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Batareya həmişəki vaxtdan əvvəl bitə bilər"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Enerjiyə Qənaət rejimi batareya istifadəsinin müddətini artırmaq üçün aktiv edilir"</string>
@@ -2292,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Tətbiqin brend şəkli"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Giriş ayarlarını yoxlayın"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> ekranınıza baxa və nəzarət edə bilər. Nəzərdən keçirmək üçün toxunun."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 450470e..3bb3f33 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -2321,4 +2321,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Imidž brenda aplikacije"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Proverite podešavanja pristupa"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> može da pregleda i kontroliše ekran. Dodirnite da biste pregledali."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index f117799..7db01d1 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -2151,17 +2151,12 @@
<string name="notification_feedback_indicator_silenced" msgid="3799442124723177262">"Гэта апавяшчэнне пераведзена ў рэжым \"Без гуку\". Націсніце тут і дайце водгук."</string>
<string name="notification_feedback_indicator_promoted" msgid="9030204303764698640">"Гэта апавяшчэнне ацэнена як важнае. Націсніце тут і дайце водгук."</string>
<string name="notification_feedback_indicator_demoted" msgid="8880309924296450875">"Гэта апавяшчэнне ацэнена як няважнае. Націсніце тут і дайце водгук."</string>
- <!-- no translation found for nas_upgrade_notification_title (8436359459300146555) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_content (5157550369837103337) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_enable_action (3046406808378726874) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_disable_action (3794833210043497982) -->
- <skip />
+ <string name="nas_upgrade_notification_title" msgid="8436359459300146555">"Палепшаныя апавяшчэнні"</string>
+ <string name="nas_upgrade_notification_content" msgid="5157550369837103337">"Прапановы дзеянняў і адказаў цяпер даюцца ў выглядзе палепшаных апавяшчэнняў. Адаптыўныя апавяшчэнні Android больш не падтрымліваюцца."</string>
+ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"ОК"</string>
+ <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"Выключыць"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"Даведацца больш"</string>
- <!-- no translation found for nas_upgrade_notification_learn_more_content (2353549817159426430) -->
- <skip />
+ <string name="nas_upgrade_notification_learn_more_content" msgid="2353549817159426430">"У версіі Android 12 Адаптыўныя апавяшчэнні Android заменены Палепшанымі апавяшчэннямі. Гэта функцыя ўпарадкоўвае вашы апавяшчэнні і паказвае прапановы дзеянняў і адказаў.\n\nПалепшаныя апавяшчэнні маюць доступ да змесціва ўсіх апавяшчэнняў, у тым ліку да асабістай інфармацыі – імён кантактаў і паведамленняў. Яшчэ гэта функцыя можа адхіляць апавяшчэнні ці адказваць на іх, напрыклад рэагаваць на тэлефонныя выклікі і кіраваць функцыяй \"Не турбаваць\"."</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Апавяшчэнне з інфармацыяй пра ўсталяваны рэжым"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Акумулятар можа разрадзіцца хутчэй, чым прыйдзе час звычайнай зарадкі"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Каб павялічыць тэрмін работы акумулятара, уключаны рэжым эканоміі зараду"</string>
@@ -2360,4 +2355,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Відарыс брэнда праграмы"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Праверце налады доступу"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> можа праглядаць экран вашай прылады і кіраваць ім. Націсніце, каб праглядзець."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 307f4ab..5a327ce 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -2287,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Изображение на търговската марка на приложението"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Проверете настройките за достъп"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> може да преглежда и управлява съдържанието на екрана ви. Докоснете за преглед."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index d41bcb9..a265821 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -1820,8 +1820,7 @@
<string name="mediasize_japanese_kahu" msgid="7290232592648122042">"Kahu"</string>
<string name="mediasize_japanese_kaku2" msgid="7477551750461028312">"Kaku2"</string>
<string name="mediasize_japanese_you4" msgid="5552111912684384833">"You4"</string>
- <!-- no translation found for mediasize_japanese_l (1326765321473431817) -->
- <skip />
+ <string name="mediasize_japanese_l" msgid="1326765321473431817">"L"</string>
<string name="mediasize_unknown_portrait" msgid="3817016220446495613">"অজানা পোর্ট্রেট"</string>
<string name="mediasize_unknown_landscape" msgid="1584741567225095325">"অজানা ল্যান্ডস্কেপ"</string>
<string name="write_fail_reason_cancelled" msgid="2344081488493969190">"বাতিল করা হয়েছে"</string>
@@ -1865,10 +1864,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 (750683025714899363) -->
- <skip />
- <!-- no translation found for battery_saver_description (5693741424234005958) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="750683025714899363">"ব্যাটারি সেভার ডার্ক থিম চালু করে এবং ব্যাকগ্রাউন্ড অ্যাক্টিভিটি, কিছু ভিজ্যুয়াল এফেক্ট ও নির্দিষ্ট ফিচারের ব্যবহার সীমিত করে বা বন্ধ করে দেয়।\n\n"<annotation id="url">"আরও জানুন"</annotation></string>
+ <string name="battery_saver_description" msgid="5693741424234005958">"ব্যাটারি সেভার ডার্ক থিম চালু করে এবং ব্যাকগ্রাউন্ড অ্যাক্টিভিটি, কিছু ভিজ্যুয়াল এফেক্ট ও নির্দিষ্ট ফিচারের ব্যবহার সীমিত করে বা বন্ধ করে দেয়।"</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>
@@ -2088,17 +2085,12 @@
<string name="notification_feedback_indicator_silenced" msgid="3799442124723177262">"এই বিজ্ঞপ্তির গুরুত্ব কমিয়ে মিউট হিসেবে সেট করা হয়েছে। মতামত জানাতে ট্যাপ করুন।"</string>
<string name="notification_feedback_indicator_promoted" msgid="9030204303764698640">"এই বিজ্ঞপ্তির গুরুত্ব বাড়ানো হয়েছে। মতামত জানাতে ট্যাপ করুন।"</string>
<string name="notification_feedback_indicator_demoted" msgid="8880309924296450875">"এই বিজ্ঞপ্তির গুরুত্ব কমানো হয়েছে। মতামত জানাতে ট্যাপ করুন।"</string>
- <!-- no translation found for nas_upgrade_notification_title (8436359459300146555) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_content (5157550369837103337) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_enable_action (3046406808378726874) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_disable_action (3794833210043497982) -->
- <skip />
+ <string name="nas_upgrade_notification_title" msgid="8436359459300146555">"উন্নত বিজ্ঞপ্তি"</string>
+ <string name="nas_upgrade_notification_content" msgid="5157550369837103337">"সাজেস্ট করা অ্যাকশন এবং উত্তর এখন উন্নত বিজ্ঞপ্তির মাধ্যমে পাওয়া যায়। Android অ্যাডাপ্টিভ বিজ্ঞপ্তি আর কাজ করবে না।"</string>
+ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"ঠিক আছে"</string>
+ <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"বন্ধ করুন"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"আরও জানুন"</string>
- <!-- no translation found for nas_upgrade_notification_learn_more_content (2353549817159426430) -->
- <skip />
+ <string name="nas_upgrade_notification_learn_more_content" msgid="2353549817159426430">"Android 12 ভার্সনে Android অ্যাডাপ্টিভ বিজ্ঞপ্তির পরিবর্তে উন্নত বিজ্ঞপ্তি এসেছে। এই ফিচারটি সাজেস্ট করা অ্যাকশন ও উত্তর দেখায় এবং আপনার বিজ্ঞপ্তি এক জায়াগায় সাজিয়ে রাখে। \n\nউন্নত বিজ্ঞপ্তি পরিচিতির নাম এবং মেসেজের মতো ব্যক্তিগত তথ্য ছাড়াও বিজ্ঞপ্তির কন্টেন্ট অ্যাক্সেস করতে পারে। এছাড়া, এই ফিচার বিজ্ঞপ্তি বাতিল করতে বা তার উত্তর দিতে পারে, যেমন ফোন কলের উত্তর দেওয়া এবং \'বিরক্ত করবে না\' মোড নিয়ন্ত্রণ করা।"</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"রুটিন মোডের তথ্য সংক্রান্ত বিজ্ঞপ্তি"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"সাধারণত যখন চার্জ দেন, তার আগে চার্জ শেষ হয়ে যেতে পারে"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"ডিভাইস বেশিক্ষণ চালু রাখতে ব্যাটারি সেভার চালু করা হয়েছে"</string>
@@ -2295,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"অ্যাপের ব্র্যান্ড ছবি"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"অ্যাক্সেস করার সেটিংস চেক করুন"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> আপনার স্ক্রিন দেখতে ও কন্ট্রোল করতে পারবে। পর্যালোচনা করতে ট্যাপ করুন।"</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index c776cac..30a2ccc 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -2321,4 +2321,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Slika robne marke za aplikaciju"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Provjerite postavke pristupa"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> može pregledati i kontrolirati vaš ekran. Dodirnite da pregledate."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index a581de6..8e0f337 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -2287,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Imatge de brànding de l\'aplicació"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Comprova la configuració d\'accés"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> pot veure i controlar la teva pantalla. Toca per revisar-ho."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index c562a8f..6c1208d 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -2355,4 +2355,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Image značky aplikace"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Zkontrolujte nastavení přístupu"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"Tuto obrazovku může zobrazit a ovládat služba <xliff:g id="SERVICE_NAME">%s</xliff:g>. Klepnutím to zkontrolujete."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 9f4f5a0..808f066 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -2085,17 +2085,12 @@
<string name="notification_feedback_indicator_silenced" msgid="3799442124723177262">"Denne notifikation blev angivet som Lydløs. Tryk for at give feedback."</string>
<string name="notification_feedback_indicator_promoted" msgid="9030204303764698640">"Denne notifikation blev placeret højere. Tryk for at give feedback."</string>
<string name="notification_feedback_indicator_demoted" msgid="8880309924296450875">"Denne notifikation blev placeret lavere. Tryk for at give feedback."</string>
- <!-- no translation found for nas_upgrade_notification_title (8436359459300146555) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_content (5157550369837103337) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_enable_action (3046406808378726874) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_disable_action (3794833210043497982) -->
- <skip />
+ <string name="nas_upgrade_notification_title" msgid="8436359459300146555">"Forbedrede notifikationer"</string>
+ <string name="nas_upgrade_notification_content" msgid="5157550369837103337">"Foreslåede handlinger og svar leveres nu via forbedrede notifikationer. Tilpassede Android-notifikationer understøttes ikke længere."</string>
+ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"OK"</string>
+ <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"Deaktiver"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"Få flere oplysninger"</string>
- <!-- no translation found for nas_upgrade_notification_learn_more_content (2353549817159426430) -->
- <skip />
+ <string name="nas_upgrade_notification_learn_more_content" msgid="2353549817159426430">"Forbedrede notifikationer erstatter automatiske Android-notifikationer i Android 12. Denne funktion viser foreslåede handlinger og svar og organiserer dine notifikationer.\n\nForbedrede notifikationer kan få adgang til indhold i notifikationer, bl.a. personlige oplysninger som f.eks. beskeder og navne på kontakter. Funktionen kan også afvise eller svare på notifikationer, f.eks. besvarelse af telefonopkald og justering af Forstyr ikke."</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Notifikation med oplysninger om rutinetilstand"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Enheden løber muligvis tør for batteri, inden du normalt oplader den"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Batterisparefunktion er aktiveret for at forlænge batteritiden"</string>
@@ -2292,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Appens brandimage"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Tjek adgangsindstillingerne"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> kan se og styre din skærm. Tryk for at se mere."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index f14273b..6a33a0a 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -1520,7 +1520,7 @@
<string name="gpsNotifTicker" msgid="3207361857637620780">"Standortabfrage von <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="gpsNotifTitle" msgid="1590033371665669570">"Standortabfrage"</string>
<string name="gpsNotifMessage" msgid="7346649122793758032">"Angefordert von <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
- <string name="gpsVerifYes" msgid="3719843080744112940">"„Ja“"</string>
+ <string name="gpsVerifYes" msgid="3719843080744112940">"Ja"</string>
<string name="gpsVerifNo" msgid="1671201856091564741">"Nein"</string>
<string name="sync_too_many_deletes" msgid="6999440774578705300">"Löschbegrenzung überschritten"</string>
<string name="sync_too_many_deletes_desc" msgid="7409327940303504440">"Es sind <xliff:g id="NUMBER_OF_DELETED_ITEMS">%1$d</xliff:g> gelöschte Elemente für <xliff:g id="TYPE_OF_SYNC">%2$s</xliff:g>, Konto <xliff:g id="ACCOUNT_NAME">%3$s</xliff:g>, vorhanden. Wie möchtest du fortfahren?"</string>
@@ -1820,8 +1820,7 @@
<string name="mediasize_japanese_kahu" msgid="7290232592648122042">"Kahu"</string>
<string name="mediasize_japanese_kaku2" msgid="7477551750461028312">"Kaku2"</string>
<string name="mediasize_japanese_you4" msgid="5552111912684384833">"You4"</string>
- <!-- no translation found for mediasize_japanese_l (1326765321473431817) -->
- <skip />
+ <string name="mediasize_japanese_l" msgid="1326765321473431817">"L"</string>
<string name="mediasize_unknown_portrait" msgid="3817016220446495613">"Unbekannt – Hochformat"</string>
<string name="mediasize_unknown_landscape" msgid="1584741567225095325">"Unbekannt – Querformat"</string>
<string name="write_fail_reason_cancelled" msgid="2344081488493969190">"Abgebrochen"</string>
@@ -1865,10 +1864,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 (750683025714899363) -->
- <skip />
- <!-- no translation found for battery_saver_description (5693741424234005958) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="750683025714899363">"Der Energiesparmodus aktiviert das dunkle Design und schränkt Hintergrundaktivitäten, einige optische Effekte und bestimmte Funktionen ein oder deaktiviert sie.\n\n"<annotation id="url">"Weitere Informationen"</annotation></string>
+ <string name="battery_saver_description" msgid="5693741424234005958">"Der Energiesparmodus aktiviert das dunkle Design und schränkt Hintergrundaktivitäten, einige optische Effekte und bestimmte Funktionen 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>
@@ -2088,17 +2085,12 @@
<string name="notification_feedback_indicator_silenced" msgid="3799442124723177262">"Diese Benachrichtigung wurde auf „Lautlos“ herabgestuft. Tippe, um Feedback zu geben."</string>
<string name="notification_feedback_indicator_promoted" msgid="9030204303764698640">"Diese Benachrichtigung wurde hochgestuft. Tippe, um Feedback zu geben."</string>
<string name="notification_feedback_indicator_demoted" msgid="8880309924296450875">"Diese Benachrichtigung wurde herabgestuft. Tippe, um Feedback zu geben."</string>
- <!-- no translation found for nas_upgrade_notification_title (8436359459300146555) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_content (5157550369837103337) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_enable_action (3046406808378726874) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_disable_action (3794833210043497982) -->
- <skip />
+ <string name="nas_upgrade_notification_title" msgid="8436359459300146555">"Erweiterte Benachrichtigungen"</string>
+ <string name="nas_upgrade_notification_content" msgid="5157550369837103337">"Die Funktion „Erweiterte Benachrichtigungen“ liefert jetzt Vorschläge für Aktionen und Antworten. Adaptive Benachrichtigungen für Android werden nicht mehr unterstützt."</string>
+ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"OK"</string>
+ <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"Ausschalten"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"Weitere Informationen"</string>
- <!-- no translation found for nas_upgrade_notification_learn_more_content (2353549817159426430) -->
- <skip />
+ <string name="nas_upgrade_notification_learn_more_content" msgid="2353549817159426430">"Die Adaptiven Benachrichtigungen wurden in Android 12 durch die Funktion „Erweiterte Benachrichtigungen“ ersetzt. Diese Funktion zeigt Vorschläge für Aktionen und Antworten an und sortiert Benachrichtigungen.\n\nDie Funktion „Erweiterte Benachrichtigungen“ kann alle Benachrichtigungen lesen, darunter auch personenbezogene Daten wie Kontaktnamen und Nachrichten. Außerdem kann sie auf Benachrichtigungen antworten oder diese schließen und so beispielsweise Anrufe entgegennehmen oder „Bitte nicht stören“ steuern."</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Infomitteilung zum Ablaufmodus"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Dein Akku könnte vor der gewöhnlichen Ladezeit leer sein"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Energiesparmodus aktiviert, um die Akkulaufzeit zu verlängern"</string>
@@ -2295,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"App-Branding-Hintergrundbild"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Zugriffseinstellungen prüfen"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> kann deinen Bildschirm sehen und steuern. Zum Prüfen tippen."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 1defb40..06a358a 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -2287,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Εικόνα επωνυμίας εφαρμογής"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Ελέγξτε τις ρυθμίσεις προσβασιμότητας"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"Η υπηρεσία <xliff:g id="SERVICE_NAME">%s</xliff:g> μπορεί να βλέπει και να ελέγχει την οθόνη σας. Πατήστε για έλεγχο."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index f123c8e..8093752 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -2287,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Application branding image"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Check access settings"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> can view and control your screen. Tap to review."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index 686bb39..96dd0de 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -2287,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Application branding image"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Check access settings"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> can view and control your screen. Tap to review."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index c8728ad..3dc2d7d 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -2287,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Application branding image"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Check access settings"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> can view and control your screen. Tap to review."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 4e71212..789a654 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -2287,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Application branding image"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Check access settings"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> can view and control your screen. Tap to review."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index e6887e9..43c951e 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -2287,4 +2287,6 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Application branding image"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Check access settings"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> can view and control your screen. Tap to review."</string>
+ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> Translated."</string>
+ <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Message translated from <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> to <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>."</string>
</resources>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index e25d927..c182190 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -2085,17 +2085,12 @@
<string name="notification_feedback_indicator_silenced" msgid="3799442124723177262">"Esta notificación descendió de a Silenciada. Presiona para enviar comentarios."</string>
<string name="notification_feedback_indicator_promoted" msgid="9030204303764698640">"Esta notificación recibió una clasificación superior. Presiona para enviar comentarios."</string>
<string name="notification_feedback_indicator_demoted" msgid="8880309924296450875">"Esta notificación recibió una clasificación inferior. Presiona para enviar comentarios."</string>
- <!-- no translation found for nas_upgrade_notification_title (8436359459300146555) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_content (5157550369837103337) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_enable_action (3046406808378726874) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_disable_action (3794833210043497982) -->
- <skip />
+ <string name="nas_upgrade_notification_title" msgid="8436359459300146555">"Notificaciones mejoradas"</string>
+ <string name="nas_upgrade_notification_content" msgid="5157550369837103337">"Las notificaciones mejoradas ahora brindan respuestas y acciones sugeridas. Ya no se admiten las notificaciones adaptables de Android."</string>
+ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"Aceptar"</string>
+ <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"Desactivar"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"Más información"</string>
- <!-- no translation found for nas_upgrade_notification_learn_more_content (2353549817159426430) -->
- <skip />
+ <string name="nas_upgrade_notification_learn_more_content" msgid="2353549817159426430">"Las notificaciones mejoradas reemplazaron a las notificaciones adaptables en Android 12. Esta función muestra respuestas y acciones sugeridas, y organiza tus notificaciones.\n\nLas notificaciones mejoradas pueden acceder a todo el contenido de notificaciones, lo que incluye información personal, como nombres de contactos y mensajes. También puede descartar o responder notificaciones, como responder llamadas y controlar la función No interrumpir."</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Notificación de información del modo de Rutinas"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Es posible que la batería se agote antes de la carga habitual"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Se activó el Ahorro de batería para extender la duración de la batería"</string>
@@ -2292,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Imagen de marca de la aplicación"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Verifica la configuración de acceso"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> puede ver y controlar tu pantalla. Presiona para revisar esta opción."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index a28553a..1e880e4 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -2085,17 +2085,12 @@
<string name="notification_feedback_indicator_silenced" msgid="3799442124723177262">"La importancia de esta notificación ha disminuido a Silencio. Toca para enviar comentarios."</string>
<string name="notification_feedback_indicator_promoted" msgid="9030204303764698640">"Esta notificación aparecerá en una posición más alta. Toca para enviar comentarios."</string>
<string name="notification_feedback_indicator_demoted" msgid="8880309924296450875">"Esta notificación aparecerá en una posición más baja. Toca para enviar comentarios."</string>
- <!-- no translation found for nas_upgrade_notification_title (8436359459300146555) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_content (5157550369837103337) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_enable_action (3046406808378726874) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_disable_action (3794833210043497982) -->
- <skip />
+ <string name="nas_upgrade_notification_title" msgid="8436359459300146555">"Notificaciones mejoradas"</string>
+ <string name="nas_upgrade_notification_content" msgid="5157550369837103337">"Ahora se sugieren acciones y respuestas mediante notificaciones mejoradas. Ya no se admiten las notificaciones adaptativas de Android."</string>
+ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"Aceptar"</string>
+ <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"Desactivar"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"Más información"</string>
- <!-- no translation found for nas_upgrade_notification_learn_more_content (2353549817159426430) -->
- <skip />
+ <string name="nas_upgrade_notification_learn_more_content" msgid="2353549817159426430">"Las notificaciones mejoradas sustituyen a las notificaciones adaptativas en Android 12. Esta nueva función te sugiere acciones y respuestas, y organiza tus notificaciones.\n\nLa función puede acceder al contenido de tus notificaciones, incluida información personal, como nombres de contactos y mensajes. También puede cerrar o responder a notificaciones; por ejemplo, puede descolgar llamadas telefónicas y controlar No molestar."</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Notificación sobre el modo rutina"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Quizás se agote la batería antes de lo habitual"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Se ha activado el modo Ahorro de batería para aumentar la duración de la batería"</string>
@@ -2292,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Imagen de marca de aplicación"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Comprueba los ajustes de acceso"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> puede ver y controlar tu pantalla. Toca para revisarlo."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index b464f93..865e9d0 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -2085,17 +2085,12 @@
<string name="notification_feedback_indicator_silenced" msgid="3799442124723177262">"Sellele märguandele määrati prioriteet Vaikne. Puudutage tagasiside andmiseks."</string>
<string name="notification_feedback_indicator_promoted" msgid="9030204303764698640">"Sellele märguandele määrati kõrgem prioriteet. Puudutage tagasiside andmiseks."</string>
<string name="notification_feedback_indicator_demoted" msgid="8880309924296450875">"Sellele märguandele määrati madalam prioriteet. Puudutage tagasiside andmiseks."</string>
- <!-- no translation found for nas_upgrade_notification_title (8436359459300146555) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_content (5157550369837103337) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_enable_action (3046406808378726874) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_disable_action (3794833210043497982) -->
- <skip />
+ <string name="nas_upgrade_notification_title" msgid="8436359459300146555">"Täiustatud märguanded"</string>
+ <string name="nas_upgrade_notification_content" msgid="5157550369837103337">"Soovitatud toiminguid ja vastuseid pakuvad nüüd täiustatud märguanded. Androidi kohanduvaid märguandeid enam ei toetata."</string>
+ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"OK"</string>
+ <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"Lülita välja"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"Lisateave"</string>
- <!-- no translation found for nas_upgrade_notification_learn_more_content (2353549817159426430) -->
- <skip />
+ <string name="nas_upgrade_notification_learn_more_content" msgid="2353549817159426430">"Androidi versioonis 12 asendasid täiustatud märguanded Androidi kohanduvad märguanded. See funktsioon näitab soovitatud toiminguid ja vastuseid ning korrastab teie märguandeid.\n\nTäiustatud märguanded pääsevad juurde märguande sisule, sh isiklikule teabele, nagu kontaktide nimed ja sõnumid. Samuti saab selle funktsiooni abil märguannetest loobuda või neile vastata (nt vastata telefonikõnedele ja juhtida funktsiooni Mitte segada)."</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Rutiinirežiimi teabe märguanne"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Aku võib enne tavapärast laadimist tühjaks saada"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Akusäästja aktiveeriti aku tööea pikendamiseks"</string>
@@ -2292,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Rakenduse brändi kujutis"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Kontrollige juurdepääsuseadeid"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> saab vaadata ja hallata teie ekraanikuva. Puudutage ülevaatamiseks."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index a6859ed..e0af24f 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -2287,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Aplikazioaren marka-irudia"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Egiaztatu sarbide-ezarpenak"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> zerbitzuak pantaila ikusi eta kontrola dezake. Sakatu berrikusteko."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 472ea61..03a962b 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -2287,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"تصویر نمانامسازی برنامه"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"بررسی تنظیمات دسترسی"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> میتواند صفحهنمایش شما را مشاهده و کنترل کند. برای مرور، ضربه بزنید."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index c51bd26..bcc6d88 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -2287,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Sovelluksen tuotemerkkikuva"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Tarkista pääsyasetukset"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> voi nähdä ja ohjata näyttöäsi. Tarkista napauttamalla."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 886c613..178ca39 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -2085,17 +2085,12 @@
<string name="notification_feedback_indicator_silenced" msgid="3799442124723177262">"Cette notification a été rétrogradée à Silencieuse. Touchez pour envoyer des commentaires."</string>
<string name="notification_feedback_indicator_promoted" msgid="9030204303764698640">"Cette notification a été élevée d\'un niveau. Touchez pour envoyer des commentaires."</string>
<string name="notification_feedback_indicator_demoted" msgid="8880309924296450875">"Cette notification a été abaissée d\'un niveau. Touchez pour envoyer des commentaires."</string>
- <!-- no translation found for nas_upgrade_notification_title (8436359459300146555) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_content (5157550369837103337) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_enable_action (3046406808378726874) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_disable_action (3794833210043497982) -->
- <skip />
+ <string name="nas_upgrade_notification_title" msgid="8436359459300146555">"Notifications améliorées"</string>
+ <string name="nas_upgrade_notification_content" msgid="5157550369837103337">"Les suggestions d\'actions et de réponses sont maintenant fournies par les notifications améliorées. Les notifications adaptatives Android ne sont plus prises en charge."</string>
+ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"OK"</string>
+ <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"Désactiver"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"En savoir plus"</string>
- <!-- no translation found for nas_upgrade_notification_learn_more_content (2353549817159426430) -->
- <skip />
+ <string name="nas_upgrade_notification_learn_more_content" msgid="2353549817159426430">"Les notifications améliorées ont remplacé les notifications adaptatives Android sous Android 12. Cette fonctionnalité vous présente des suggestions d\'actions et de réponse, et organise vos notifications.\n\nLes notifications améliorées peuvent accéder au contenu de toutes les notifications, y compris les renseignements personnels comme le nom des contacts et les messages. Cette fonctionnalité peut aussi fermer des notifications ou interagir avec elles, comme répondre aux appels téléphoniques et gérer le mode Ne pas déranger."</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Notification d\'information du mode Routine"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"La pile pourrait s\'épuiser avant la charge habituelle"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Le mode Économiseur de pile est activé afin de prolonger l\'autonomie"</string>
@@ -2292,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Image de marque de l\'application"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Vérifiez les paramètres d\'accès"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> peut voir et contrôler votre écran. Touchez pour examiner."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 9524cd5..d4e8d57 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -1820,8 +1820,7 @@
<string name="mediasize_japanese_kahu" msgid="7290232592648122042">"Kahu"</string>
<string name="mediasize_japanese_kaku2" msgid="7477551750461028312">"Kaku2"</string>
<string name="mediasize_japanese_you4" msgid="5552111912684384833">"You4"</string>
- <!-- no translation found for mediasize_japanese_l (1326765321473431817) -->
- <skip />
+ <string name="mediasize_japanese_l" msgid="1326765321473431817">"L"</string>
<string name="mediasize_unknown_portrait" msgid="3817016220446495613">"Taille inconnue au format portrait"</string>
<string name="mediasize_unknown_landscape" msgid="1584741567225095325">"Taille inconnue au format paysage"</string>
<string name="write_fail_reason_cancelled" msgid="2344081488493969190">"Tâche annulée."</string>
@@ -1865,10 +1864,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 (750683025714899363) -->
- <skip />
- <!-- no translation found for battery_saver_description (5693741424234005958) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="750683025714899363">"L\'économiseur de batterie active le thème sombre et limite ou désactive les activités en arrière-plan et certains effets visuels et fonctionnalités.\n\n"<annotation id="url">"En savoir plus"</annotation></string>
+ <string name="battery_saver_description" msgid="5693741424234005958">"L\'économiseur de batterie active le thème sombre et limite ou désactive les activités en arrière-plan et certains effets visuels et fonctionnalités."</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>
@@ -2088,17 +2085,12 @@
<string name="notification_feedback_indicator_silenced" msgid="3799442124723177262">"Cette notification a été abaissée à la catégorie \"Silencieux\". Appuyez ici pour donner votre avis."</string>
<string name="notification_feedback_indicator_promoted" msgid="9030204303764698640">"Cette notification a été élevée d\'un niveau. Appuyez ici pour donner votre avis."</string>
<string name="notification_feedback_indicator_demoted" msgid="8880309924296450875">"Cette notification a été abaissée d\'un niveau. Appuyez ici pour donner votre avis."</string>
- <!-- no translation found for nas_upgrade_notification_title (8436359459300146555) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_content (5157550369837103337) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_enable_action (3046406808378726874) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_disable_action (3794833210043497982) -->
- <skip />
+ <string name="nas_upgrade_notification_title" msgid="8436359459300146555">"Notifications améliorées"</string>
+ <string name="nas_upgrade_notification_content" msgid="5157550369837103337">"Les actions et réponses suggérées sont maintenant fournies via les notifications améliorées. Les notifications intelligentes Android ne sont plus disponibles."</string>
+ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"OK"</string>
+ <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"Désactiver"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"En savoir plus"</string>
- <!-- no translation found for nas_upgrade_notification_learn_more_content (2353549817159426430) -->
- <skip />
+ <string name="nas_upgrade_notification_learn_more_content" msgid="2353549817159426430">"Les notifications améliorées remplacent les notifications intelligentes dans Android 12. Cette fonctionnalité affiche les actions et réponses suggérées, et organise vos notifications.\n\nElle a accès au contenu des notifications, y compris aux informations personnelles comme le nom des contacts et les messages. Elle peut aussi fermer les notifications ou effectuer des actions, comme répondre à un appel téléphonique et contrôler le mode Ne pas déranger."</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Notification d\'information du mode Routine"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Vous risquez d\'être à court de batterie plus tôt que prévu"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Économiseur de batterie activé pour prolonger l\'autonomie"</string>
@@ -2295,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Image de branding de l\'application"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Vérifiez les paramètres d\'accès"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> peut afficher et contrôler votre écran. Appuyez ici pour en savoir plus."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index 13cbdb3..1b8a511 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -2287,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Imaxe de marca da aplicación"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Comproba a configuración do acceso"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"Agora <xliff:g id="SERVICE_NAME">%s</xliff:g> pode ver e controlar a túa pantalla. Toca para revisalo."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index af0c553..8f85cd1 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -1820,8 +1820,7 @@
<string name="mediasize_japanese_kahu" msgid="7290232592648122042">"કહુ"</string>
<string name="mediasize_japanese_kaku2" msgid="7477551750461028312">"કાકુ2"</string>
<string name="mediasize_japanese_you4" msgid="5552111912684384833">"You4"</string>
- <!-- no translation found for mediasize_japanese_l (1326765321473431817) -->
- <skip />
+ <string name="mediasize_japanese_l" msgid="1326765321473431817">"L"</string>
<string name="mediasize_unknown_portrait" msgid="3817016220446495613">"અજાણ્યું પોર્ટ્રેટ"</string>
<string name="mediasize_unknown_landscape" msgid="1584741567225095325">"અજાણ્યું લેન્ડસ્કેપ"</string>
<string name="write_fail_reason_cancelled" msgid="2344081488493969190">"રદ થઈ"</string>
@@ -1865,10 +1864,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 (750683025714899363) -->
- <skip />
- <!-- no translation found for battery_saver_description (5693741424234005958) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="750683025714899363">"બૅટરી સેવર ઘેરી થીમની સુવિધા ચાલુ કરે છે અને બૅકગ્રાઉન્ડમાં થતી પ્રવૃત્તિ, કેટલીક વિઝ્યુઅલ ઇફેક્ટ અને કેટલીક સુવિધાઓને મર્યાદિત કે બંધ કરે છે.\n\n"<annotation id="url">"વધુ જાણો"</annotation></string>
+ <string name="battery_saver_description" msgid="5693741424234005958">"બૅટરી સેવર ઘેરી થીમની સુવિધા ચાલુ કરે છે અને બૅકગ્રાઉન્ડમાં થતી પ્રવૃત્તિ, કેટલીક વિઝ્યુઅલ ઇફેક્ટ અને કેટલીક સુવિધાઓને મર્યાદિત કે બંધ કરે છે."</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>
@@ -2295,4 +2292,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"ઍપ્લિકેશનની બ્રાંડિંગ છબી"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"ઍક્સેસના સેટિંગ ચેક કરો"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> તમારી સ્ક્રીન જોઈ અને નિયંત્રિત કરી શકે છે. રિવ્યૂ કરવા માટે ટૅપ કરો."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 866f2ef..24f5a47 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -2085,17 +2085,12 @@
<string name="notification_feedback_indicator_silenced" msgid="3799442124723177262">"इस सूचना के मिलने पर होने वाली आवाज़ बंद कर दी गई है. सुझाव/शिकायत/राय देने के लिए टैप करें."</string>
<string name="notification_feedback_indicator_promoted" msgid="9030204303764698640">"इस सूचना को रैंकिंग में ऊपर किया गया था. सुझाव/शिकायत/राय देने के लिए टैप करें."</string>
<string name="notification_feedback_indicator_demoted" msgid="8880309924296450875">"इस सूचना को रैंकिंग में नीचे किया गया था. सुझाव/शिकायत/राय देने के लिए टैप करें."</string>
- <!-- no translation found for nas_upgrade_notification_title (8436359459300146555) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_content (5157550369837103337) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_enable_action (3046406808378726874) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_disable_action (3794833210043497982) -->
- <skip />
+ <string name="nas_upgrade_notification_title" msgid="8436359459300146555">"बेहतर सूचनाएं"</string>
+ <string name="nas_upgrade_notification_content" msgid="5157550369837103337">"\'बेहतर सूचनाएं\' सुविधा अब कार्रवाइयों और जवाबों के लिए सुझाव उपलब्ध कराती है. Android की, ज़रूरत के हिसाब से सूचनाएं पाने की सुविधा अब काम नहीं करती है."</string>
+ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"चालू करें"</string>
+ <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"बंद करें"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"ज़्यादा जानें"</string>
- <!-- no translation found for nas_upgrade_notification_learn_more_content (2353549817159426430) -->
- <skip />
+ <string name="nas_upgrade_notification_learn_more_content" msgid="2353549817159426430">"Android 12 में, ज़रूरत के हिसाब से सूचनाएं पाने की सुविधा की जगह अब \'बेहतर सूचनाएं\' सुविधा काम करेगी. यह सुविधा आपको कार्रवाइयों और जवाबों के सुझाव दिखाती है. साथ ही, आपके डिवाइस में मिलने वाली सूचनाओं को व्यवस्थित भी करती है.\n\n\'बेहतर सूचनाएं\' सुविधा, डिवाइस पर मिलने वाली सभी सूचनाओं का कॉन्टेंट ऐक्सेस कर सकती है. इसमें आपकी निजी जानकारी, जैसे कि संपर्कों के नाम और मैसेज शामिल हैं. यह सुविधा, सूचनाओं को रद्द कर सकती है या उनका जवाब भी दे सकती है, जैसे कि फ़ोन कॉल का जवाब देना और \'परेशान न करें\' को कंट्रोल करना."</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"रूटीन मोड जानकारी की सूचना"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"बैटरी आम तौर पर जितने समय चलती है, उससे पहले खत्म हो सकती है"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"बैटरी लाइफ़ बढ़ाने के लिए \'बैटरी सेवर\' चालू हो गया है"</string>
@@ -2292,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"ऐप्लिकेशन की ब्रैंड इमेज"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"ऐक्सेस से जुड़ी सेटिंग देखें"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> आपकी स्क्रीन को देख सकता है और कंट्रोल कर सकता है. ऐक्सेस की समीक्षा करने के लिए टैप करें."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 7bc5eda..edb7c3a 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -2321,4 +2321,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Imidž robne marke aplikacije"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Provjerite postavke pristupa"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> može pregledavati i kontrolirati vaš zaslon. Dodirnite za pregled."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 9fa0f28..aa4d42b 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -2287,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Alkalmazás márkaképe"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Ellenőrizze a hozzáférési beállításokat"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"A(z) <xliff:g id="SERVICE_NAME">%s</xliff:g> megtekintheti és irányíthatja képernyőjét. Koppintson az áttekintéshez."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index b6d59c6..22810e4 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -2085,17 +2085,12 @@
<string name="notification_feedback_indicator_silenced" msgid="3799442124723177262">"Այս ծանուցման կարևորության մակարդակը իջեցվել է և դարձել անձայն։ Հպեք՝ կարծիք հայտնելու համար։"</string>
<string name="notification_feedback_indicator_promoted" msgid="9030204303764698640">"Այս ծանուցման կարևորության մակարդակը բարձրացվել է։ Հպեք՝ կարծիք հայտնելու համար։"</string>
<string name="notification_feedback_indicator_demoted" msgid="8880309924296450875">"Այս ծանուցման կարևորության մակարդակն իջեցվել է։ Հպեք՝ կարծիք հայտնելու համար։"</string>
- <!-- no translation found for nas_upgrade_notification_title (8436359459300146555) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_content (5157550369837103337) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_enable_action (3046406808378726874) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_disable_action (3794833210043497982) -->
- <skip />
+ <string name="nas_upgrade_notification_title" msgid="8436359459300146555">"Ընդլայնված ծանուցումներ"</string>
+ <string name="nas_upgrade_notification_content" msgid="5157550369837103337">"Ընդլայնված ծանուցումներն այժմ տրամադրում են գործողությունների և պատասխանների առաջարկներ։ Android-ի հարմարվող ծանուցումներն այլևս չեն աջակցվում։"</string>
+ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"Եղավ"</string>
+ <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"Անջատել"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"Իմանալ ավելին"</string>
- <!-- no translation found for nas_upgrade_notification_learn_more_content (2353549817159426430) -->
- <skip />
+ <string name="nas_upgrade_notification_learn_more_content" msgid="2353549817159426430">"Android 12-ում ընդլայնված ծանուցումները փոխարինում են Android-ի հարմարվող ծանուցումներին։ Այս գործառույթը դասավորում է ձեր բոլոր ծանուցումները և առաջարկում գործողություններ և պատասխաններ։\n\nԸնդլայնված ծանուցումներին հասանելի է բոլոր ծանուցումների պարունակությունը, ներառյալ անձնական տվյալները, օրինակ՝ կոնտակտների անուններն ու հաղորդագրությունները։ Այս գործառույթը կարող է նաև փակել ծանուցումները կամ սեղմել դրանցում առկա կոճակները, այդ թվում՝ պատասխանել հեռախոսազանգերի և կառավարել «Չանհանգստացնել» ռեժիմը։"</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Ծանուցում լիցքավորման մասին"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Մարտկոցը կարող է սովորականից շուտ սպառվել"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Մարտկոցի կյանքը երկարացնելու համար ակտիվացվել է մարտկոցի տնտեսման ռեժիմը"</string>
@@ -2292,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Հավելվածի բրենդային պատկեր"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Ստուգեք մուտքի կարգավորումները"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> ծառայությունը կարող է դիտել և կառավարել ձեր էկրանի բովանդակությունը։ Հպեք՝ մանրամասներն իմանալու համար։"</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index e782377..94a501a 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -2287,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Brand image aplikasi"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Periksa setelan akses"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> dapat melihat dan mengontrol layar Anda. Ketuk untuk meninjau."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index 0a834fa..0a7fa5b 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -2287,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Mynd af merki forrits"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Skoða aðgangsstillingar"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> getur skoðað og stjórnað skjánum hjá þér. Ýttu til að skoða."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 21c7aaa..184ca91 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -2287,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Immagine del branding dell\'applicazione"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Controlla le impostazioni di accesso"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> può visualizzare e controllare il tuo schermo. Tocca per verificare."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index ae0abb4..aecd79b 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -2151,17 +2151,12 @@
<string name="notification_feedback_indicator_silenced" msgid="3799442124723177262">"ההתראה הזו הורדה בדרגה ל\'שקטה\'. יש להקיש כדי לשלוח משוב."</string>
<string name="notification_feedback_indicator_promoted" msgid="9030204303764698640">"דירוג ההתראה הזו הוגבה. יש להקיש כדי לשלוח משוב."</string>
<string name="notification_feedback_indicator_demoted" msgid="8880309924296450875">"ההתראה הזו דורגה נמוך יותר. יש להקיש כדי לשלוח משוב."</string>
- <!-- no translation found for nas_upgrade_notification_title (8436359459300146555) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_content (5157550369837103337) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_enable_action (3046406808378726874) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_disable_action (3794833210043497982) -->
- <skip />
+ <string name="nas_upgrade_notification_title" msgid="8436359459300146555">"התראות משופרות"</string>
+ <string name="nas_upgrade_notification_content" msgid="5157550369837103337">"ההתראות המשופרות מספקות מעכשיו הצעות לפעולות ולתשובות. אין יותר תמיכה בהתראות מותאמות ל-Android."</string>
+ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"אישור"</string>
+ <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"השבתה"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"מידע נוסף"</string>
- <!-- no translation found for nas_upgrade_notification_learn_more_content (2353549817159426430) -->
- <skip />
+ <string name="nas_upgrade_notification_learn_more_content" msgid="2353549817159426430">"ההתראות המשופרות החליפו את ההתראות המותאמות ל-Android ב-Android 12. התכונה הזו מציגה הצעות לפעולות ולתשובות ומארגנת את ההתראות שלך.\n\nההתראות המשופרות יכולות לקבל גישה לתוכן של התראות, כולל מידע אישי כמו שמות אנשי קשר והודעות. התכונה הזו יכולה גם לסגור התראות או להשיב להן, למשל מענה לשיחות טלפון ושליטה בתכונה \'נא לא להפריע\'."</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"התראת מידע לגבי מצב שגרתי"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"הסוללה עלולה להתרוקן לפני המועד הרגיל של הטעינה"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"תכונת החיסכון בסוללה הופעלה כדי להאריך את חיי הסוללה"</string>
@@ -2360,4 +2355,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"תדמית המותג של האפליקציה"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"בדיקה של הגדרות הגישה"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"לשירות <xliff:g id="SERVICE_NAME">%s</xliff:g> יש הרשאה להצגת המסך ושליטה בו. אפשר להקיש כדי לבדוק."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 65e1849..90495be 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1820,8 +1820,7 @@
<string name="mediasize_japanese_kahu" msgid="7290232592648122042">"Kahu"</string>
<string name="mediasize_japanese_kaku2" msgid="7477551750461028312">"角2"</string>
<string name="mediasize_japanese_you4" msgid="5552111912684384833">"洋4"</string>
- <!-- no translation found for mediasize_japanese_l (1326765321473431817) -->
- <skip />
+ <string name="mediasize_japanese_l" msgid="1326765321473431817">"L"</string>
<string name="mediasize_unknown_portrait" msgid="3817016220446495613">"縦向き不明"</string>
<string name="mediasize_unknown_landscape" msgid="1584741567225095325">"横向き不明"</string>
<string name="write_fail_reason_cancelled" msgid="2344081488493969190">"キャンセルされました"</string>
@@ -1865,10 +1864,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 (750683025714899363) -->
- <skip />
- <!-- no translation found for battery_saver_description (5693741424234005958) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="750683025714899363">"バッテリー セーバーを有効にすると、ダークテーマが ON になり、バックグラウンド アクティビティ、一部の視覚効果、特定の機能が制限されるか OFF になります。\n\n"<annotation id="url">"詳細"</annotation></string>
+ <string name="battery_saver_description" msgid="5693741424234005958">"バッテリー セーバーを有効にすると、ダークテーマが 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>
@@ -2088,17 +2085,12 @@
<string name="notification_feedback_indicator_silenced" msgid="3799442124723177262">"この通知の重要度がサイレントに下がりました。タップしてフィードバックをお送りください。"</string>
<string name="notification_feedback_indicator_promoted" msgid="9030204303764698640">"この通知の重要度が上がりました。タップしてフィードバックをお送りください。"</string>
<string name="notification_feedback_indicator_demoted" msgid="8880309924296450875">"この通知の重要度が下がりました。タップしてフィードバックをお送りください。"</string>
- <!-- no translation found for nas_upgrade_notification_title (8436359459300146555) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_content (5157550369837103337) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_enable_action (3046406808378726874) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_disable_action (3794833210043497982) -->
- <skip />
+ <string name="nas_upgrade_notification_title" msgid="8436359459300146555">"拡張通知"</string>
+ <string name="nas_upgrade_notification_content" msgid="5157550369837103337">"操作や返信の候補が拡張通知から提供されるようになりました。Android 通知の自動調整はサポートを終了しました。"</string>
+ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"OK"</string>
+ <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"OFF にする"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"詳細"</string>
- <!-- no translation found for nas_upgrade_notification_learn_more_content (2353549817159426430) -->
- <skip />
+ <string name="nas_upgrade_notification_learn_more_content" msgid="2353549817159426430">"Android 12 では Android 通知の自動調整が拡張通知に切り替えられました。この機能により、操作や返信の候補が提示され、通知が整理されます。\n\n拡張通知は通知コンテンツにアクセスできます。これには、連絡先の名前などの個人情報やメッセージも含まれます。また、この機能は、通知を非表示にしたり通知に応答したりすることもできます。たとえば、電話に出ることやサイレント モードを管理することができます。"</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"ルーティン モード情報の通知"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"通常の充電を行う前に電池が切れる可能性があります"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"電池を長持ちさせるため、バッテリー セーバーが有効になりました"</string>
@@ -2295,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"アプリのブランド イメージ"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"アクセス設定の確認"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> は画面を参照、操作できます。タップしてご確認ください。"</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index b8d1e2d..3f1c8b6 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -2287,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"აპლიკაციის ბრენდის სურათი"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"სწრაფი წვდომის პარამეტრები"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g>-ს შეუძლია თქვენი ეკრანის ნახვა და მართვა. შეეხეთ გადასახედად."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index abddce1..2614264 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -2085,17 +2085,12 @@
<string name="notification_feedback_indicator_silenced" msgid="3799442124723177262">"Бұл хабарландырудың маңыздылық деңгейі \"Үнсіз\" санатына төмендетілді. Пікір қалдыру үшін түртіңіз."</string>
<string name="notification_feedback_indicator_promoted" msgid="9030204303764698640">"Бұл хабарландырудың маңыздылық деңгейі көтерілді. Пікір қалдыру үшін түртіңіз."</string>
<string name="notification_feedback_indicator_demoted" msgid="8880309924296450875">"Бұл хабарландырудың маңыздылық деңгейі төмендетілді. Пікір қалдыру үшін түртіңіз."</string>
- <!-- no translation found for nas_upgrade_notification_title (8436359459300146555) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_content (5157550369837103337) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_enable_action (3046406808378726874) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_disable_action (3794833210043497982) -->
- <skip />
+ <string name="nas_upgrade_notification_title" msgid="8436359459300146555">"Кеңейтілген хабарландырулар"</string>
+ <string name="nas_upgrade_notification_content" msgid="5157550369837103337">"Ұсынылған әрекеттер мен жауаптар енді кеңейтілген хабарландырулар функциясы арқылы қамтамасыз етіледі. Android-тың \"Бейімделетін хабарландырулар\" функциясына бұдан былай қолдау көрсетілмейді."</string>
+ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"Жарайды"</string>
+ <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"Өшіру"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"Толығырақ"</string>
- <!-- no translation found for nas_upgrade_notification_learn_more_content (2353549817159426430) -->
- <skip />
+ <string name="nas_upgrade_notification_learn_more_content" msgid="2353549817159426430">"Android 12 жүйесінде кеңейтілген хабарландырулар функциясы \"Бейімделетін хабарландырулар\" функциясын алмастырды. Бұл функция ұсынылған әрекеттер мен жауаптарды көрсетіп, хабарландыруларыңызды ретке келтіреді.\n\nОл хабарландыру мазмұнын, соның ішінде жеке ақпаратыңызды (мысалы, контакт атаулары мен хабарлар) пайдалана алады. Сондай-ақ бұл функция арқылы хабарландыруларды жабуға немесе оларға жауап беруге (мысалы, телефон қоңырауларына жауап беру және \"Мазаламау\" режимін басқару) болады."</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Режим туралы хабарландыру"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Батарея заряды азаюы мүмкін"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Батарея ұзаққа жетуі үшін, Батареяны үнемдеу режимі іске қосылды"</string>
@@ -2292,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Қолданба брендін ілгері жылжыту кескіні"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Пайдалану параметрлерін тексеріңіз"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> экраныңызды көріп, оны басқара алады. Өту үшін түртіңіз."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index 4834695..e00bed0 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -2085,17 +2085,12 @@
<string name="notification_feedback_indicator_silenced" msgid="3799442124723177262">"ការជូនដំណឹងនេះត្រូវបានបន្ទាបតំណែងទៅស្ងាត់។ សូមចុចដើម្បីផ្ដល់មតិកែលម្អ។"</string>
<string name="notification_feedback_indicator_promoted" msgid="9030204303764698640">"ការជូនដំណឹងនេះត្រូវបានចាត់ថ្នាក់ខ្ពស់ជាងមុន។ សូមចុចដើម្បីផ្ដល់មតិកែលម្អ។"</string>
<string name="notification_feedback_indicator_demoted" msgid="8880309924296450875">"ការជូនដំណឹងនេះត្រូវបានចាត់ថ្នាក់ទាបជាងមុន។ សូមចុចដើម្បីផ្ដល់មតិកែលម្អ។"</string>
- <!-- no translation found for nas_upgrade_notification_title (8436359459300146555) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_content (5157550369837103337) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_enable_action (3046406808378726874) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_disable_action (3794833210043497982) -->
- <skip />
+ <string name="nas_upgrade_notification_title" msgid="8436359459300146555">"ការជូនដំណឹងប្រសើរជាងមុន"</string>
+ <string name="nas_upgrade_notification_content" msgid="5157550369837103337">"ឥឡូវនេះ ការឆ្លើយតប និងសកម្មភាពដែលបានណែនាំត្រូវបានផ្ដល់ដោយការជូនដំណឹងប្រសើរជាងមុន។ មិនអាចប្រើការជូនដំណឹងដែលមានភាពបត់បែនរបស់ Android បានទៀតទេ។"</string>
+ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"យល់ព្រម"</string>
+ <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"បិទ"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"ស្វែងយល់បន្ថែម"</string>
- <!-- no translation found for nas_upgrade_notification_learn_more_content (2353549817159426430) -->
- <skip />
+ <string name="nas_upgrade_notification_learn_more_content" msgid="2353549817159426430">"ការជូនដំណឹងប្រសើរជាងមុនបានជំនួសការជូនដំណឹងដែលមានភាពបត់បែន Android នៅក្នុង Android 12។ មុខងារនេះបង្ហាញការឆ្លើយតប និងសកម្មភាពដែលបានណែនាំ ព្រមទាំងរៀបចំការជូនដំណឹងរបស់អ្នក។\n\nការជូនដំណឹងប្រសើរជាងមុនអាចចូលប្រើខ្លឹមសារនៃការជូនដំណឹង រួមទាំងព័ត៌មានផ្ទាល់ខ្លួនដូចជា ឈ្មោះទំនាក់ទំនង និងសារជាដើម។ មុខងារនេះក៏អាចច្រានចោល ឬឆ្លើយតបនឹងការជូនដំណឹងដូចជា ការទទួលការហៅទូរសព្ទ និងការគ្រប់គ្រងមុខងារកុំរំខានផងដែរ។"</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"ការជូនដំណឹងព័ត៌មានរបស់មុខងារទម្លាប់"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"ថ្មអាចនឹងអស់ មុនពេលសាកថ្មធម្មតា"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"បានបើកដំណើរការមុខងារសន្សំថ្ម ដើម្បីបង្កើនកម្រិតថាមពលថ្ម"</string>
@@ -2292,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"រូបភាពផ្សព្វផ្សាយម៉ាកកម្មវិធី"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"ពិនិត្យមើលការកំណត់សិទ្ធិចូលប្រើ"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> អាចមើល និងគ្រប់គ្រងអេក្រង់របស់អ្នកបាន។ សូមចុច ដើម្បីពិនិត្យមើល។"</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index 07e0ca3..7ac785b 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -1773,28 +1773,17 @@
<string name="mediasize_na_monarch" msgid="4396943937986136896">"ಮೊನಾರ್ಕ್"</string>
<string name="mediasize_na_quarto" msgid="2119101847712239885">"ಕ್ವಾರ್ಟೊ"</string>
<string name="mediasize_na_foolscap" msgid="5011612828564394648">"Foolscap"</string>
- <!-- no translation found for mediasize_na_ansi_c (3104916921818289618) -->
- <skip />
- <!-- no translation found for mediasize_na_ansi_d (254005964819282724) -->
- <skip />
- <!-- no translation found for mediasize_na_ansi_e (4424174989686785675) -->
- <skip />
- <!-- no translation found for mediasize_na_ansi_f (146980362213260987) -->
- <skip />
- <!-- no translation found for mediasize_na_arch_a (5280681822380032361) -->
- <skip />
- <!-- no translation found for mediasize_na_arch_b (2113344093437297427) -->
- <skip />
- <!-- no translation found for mediasize_na_arch_c (971002546186856623) -->
- <skip />
- <!-- no translation found for mediasize_na_arch_d (6450996075335049806) -->
- <skip />
- <!-- no translation found for mediasize_na_arch_e (6782708486949266519) -->
- <skip />
- <!-- no translation found for mediasize_na_arch_e1 (4707138568738504275) -->
- <skip />
- <!-- no translation found for mediasize_na_super_b (6964127155618393178) -->
- <skip />
+ <string name="mediasize_na_ansi_c" msgid="3104916921818289618">"ANSI C"</string>
+ <string name="mediasize_na_ansi_d" msgid="254005964819282724">"ANSI D"</string>
+ <string name="mediasize_na_ansi_e" msgid="4424174989686785675">"ANSI E"</string>
+ <string name="mediasize_na_ansi_f" msgid="146980362213260987">"ANSI F"</string>
+ <string name="mediasize_na_arch_a" msgid="5280681822380032361">"Arch A"</string>
+ <string name="mediasize_na_arch_b" msgid="2113344093437297427">"Arch B"</string>
+ <string name="mediasize_na_arch_c" msgid="971002546186856623">"Arch C"</string>
+ <string name="mediasize_na_arch_d" msgid="6450996075335049806">"Arch D"</string>
+ <string name="mediasize_na_arch_e" msgid="6782708486949266519">"Arch E"</string>
+ <string name="mediasize_na_arch_e1" msgid="4707138568738504275">"Arch E1"</string>
+ <string name="mediasize_na_super_b" msgid="6964127155618393178">"Super B"</string>
<string name="mediasize_chinese_roc_8k" msgid="411670106572707544">"ROC 8K"</string>
<string name="mediasize_chinese_roc_16k" msgid="7496706798725321898">"ROC 16K"</string>
<string name="mediasize_chinese_prc_1" msgid="946949835711037253">"PRC 1"</string>
@@ -2096,17 +2085,12 @@
<string name="notification_feedback_indicator_silenced" msgid="3799442124723177262">"ಈ ಅಧಿಸೂಚನೆಗೆ ಸೈಲೆಂಟ್ಗೆ ಹಿಂಬಡ್ತಿ ನೀಡಲಾಗಿದೆ. ಪ್ರತಿಕ್ರಿಯೆ ನೀಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
<string name="notification_feedback_indicator_promoted" msgid="9030204303764698640">"ಈ ಅಧಿಸೂಚನೆಗೆ ಮೇಲಿನ ಸ್ಥಾನವನ್ನು ನೀಡಲಾಗಿದೆ. ಪ್ರತಿಕ್ರಿಯೆ ನೀಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
<string name="notification_feedback_indicator_demoted" msgid="8880309924296450875">"ಈ ಅಧಿಸೂಚನೆಗೆ ಕೆಳಗಿನ ಸ್ಥಾನವನ್ನು ನೀಡಲಾಗಿದೆ. ಪ್ರತಿಕ್ರಿಯೆ ನೀಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
- <!-- no translation found for nas_upgrade_notification_title (8436359459300146555) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_content (5157550369837103337) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_enable_action (3046406808378726874) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_disable_action (3794833210043497982) -->
- <skip />
+ <string name="nas_upgrade_notification_title" msgid="8436359459300146555">"ವರ್ಧಿತ ಅಧಿಸೂಚನೆಗಳು"</string>
+ <string name="nas_upgrade_notification_content" msgid="5157550369837103337">"ಸೂಚಿಸಲಾದ ಕ್ರಿಯೆಗಳು ಮತ್ತು ಪ್ರತ್ಯುತ್ತರಗಳನ್ನು ಈಗ ವರ್ಧಿತ ಅಧಿಸೂಚನೆಗಳಿಂದ ಒದಗಿಸಲಾಗಿದೆ. Android ಅಡಾಪ್ಟಿವ್ ಅಧಿಸೂಚನೆಗಳು ಇನ್ನು ಮುಂದೆ ಬೆಂಬಲಿಸುವುದಿಲ್ಲ."</string>
+ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"ಸರಿ"</string>
+ <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"ಆಫ್ ಮಾಡಿ"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"ಇನ್ನಷ್ಟು ತಿಳಿಯಿರಿ"</string>
- <!-- no translation found for nas_upgrade_notification_learn_more_content (2353549817159426430) -->
- <skip />
+ <string name="nas_upgrade_notification_learn_more_content" msgid="2353549817159426430">"ವರ್ಧಿತ ಅಧಿಸೂಚನೆಗಳು Android 12 ರಲ್ಲಿ ಆಂಡ್ರಾಯ್ಡ್ ಅಡಾಪ್ಟಿವ್ ಅಧಿಸೂಚನೆಗಳನ್ನು ಬದಲಾಯಿಸಿವೆ. ಈ ವೈಶಿಷ್ಟ್ಯವು ಸೂಚಿಸಿದ ಕ್ರಿಯೆಗಳು ಮತ್ತು ಪ್ರತ್ಯುತ್ತರಗಳನ್ನು ತೋರಿಸುತ್ತದೆ ಮತ್ತು ನಿಮ್ಮ ಅಧಿಸೂಚನೆಗಳನ್ನು ಆಯೋಜಿಸುತ್ತದೆ.\n\nವರ್ಧಿತ ಅಧಿಸೂಚನೆಗಳು ಸಂಪರ್ಕ ಹೆಸರುಗಳು ಮತ್ತು ಸಂದೇಶಗಳಂತಹ ವೈಯಕ್ತಿಕ ಮಾಹಿತಿಯನ್ನು ಒಳಗೊಂಡಂತೆ ಎಲ್ಲಾ ಅಧಿಸೂಚನೆ ವಿಷಯವನ್ನು ಪ್ರವೇಶಿಸಬಹುದು. ಈ ವೈಶಿಷ್ಟ್ಯವು ಫೋನ್ ಕರೆಗಳಿಗೆ ಉತ್ತರಿಸುವುದು ಮತ್ತು \'ಅಡಚಣೆ ಮಾಡಬೇಡಿ\' ಅನ್ನು ನಿಯಂತ್ರಿಸುವಂತಹ ಅಧಿಸೂಚನೆಗಳನ್ನು ವಜಾಗೊಳಿಸಬಹುದು ಅಥವಾ ಪ್ರತಿಕ್ರಿಯಿಸಬಹುದು."</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"ದೈನಂದಿನ ಸ್ಥಿತಿಯ ಮಾಹಿತಿಯ ಅಧಿಸೂಚನೆ"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"ಚಾರ್ಜ್ಗೆ ಮೊದಲೆ ಬ್ಯಾಟರಿ ಮುಗಿದು ಬಿಡಬಹುದು"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"ಬ್ಯಾಟರಿ ಅವಧಿ ಹೆಚ್ಚಿಸಲು ಬ್ಯಾಟರಿ ಸೇವರ್ ಸಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
@@ -2303,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"ಅಪ್ಲಿಕೇಶನ್ ಬ್ರ್ಯಾಂಡಿಂಗ್ ಚಿತ್ರ"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"ಪ್ರವೇಶ ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ಪರಿಶೀಲಿಸಿ"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ ಅನ್ನು ವೀಕ್ಷಿಸಬಹುದು ಮತ್ತು ನಿಯಂತ್ರಿಸಬಹುದು. ಪರಿಶೀಲಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 8208182..c670af2 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -2085,17 +2085,12 @@
<string name="notification_feedback_indicator_silenced" msgid="3799442124723177262">"이 알림의 중요도가 무음으로 하향되었습니다. 의견을 보내려면 탭하세요."</string>
<string name="notification_feedback_indicator_promoted" msgid="9030204303764698640">"이전에 이 알림의 중요도는 더 높았습니다. 의견을 보내려면 탭하세요."</string>
<string name="notification_feedback_indicator_demoted" msgid="8880309924296450875">"이전에 이 알림의 중요도는 더 낮았습니다. 의견을 보내려면 탭하세요."</string>
- <!-- no translation found for nas_upgrade_notification_title (8436359459300146555) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_content (5157550369837103337) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_enable_action (3046406808378726874) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_disable_action (3794833210043497982) -->
- <skip />
+ <string name="nas_upgrade_notification_title" msgid="8436359459300146555">"개선된 알림"</string>
+ <string name="nas_upgrade_notification_content" msgid="5157550369837103337">"이제 개선된 알림을 통해 추천 작업과 답장이 제공됩니다. Android 적응형 알림은 더 이상 지원되지 않습니다."</string>
+ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"확인"</string>
+ <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"사용 중지"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"자세히 알아보기"</string>
- <!-- no translation found for nas_upgrade_notification_learn_more_content (2353549817159426430) -->
- <skip />
+ <string name="nas_upgrade_notification_learn_more_content" msgid="2353549817159426430">"Android 12에서는 Android 적응형 알림이 개선된 알림으로 대체됩니다. 이 기능은 추천 작업과 답장을 표시하고 알림을 정리해 줍니다.\n\n개선된 알림은 연락처 이름과 메시지 등 개인 정보가 포함된 알림 내용에 액세스할 수 있습니다. 이 기능은 전화 받기와 방해 금지 모드 제어와 같이 알림을 닫거나 알림을 처리할 수도 있습니다."</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"루틴 모드 정보 알림"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"평소에 충전하는 시간 전에 배터리가 소진될 수 있습니다."</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"배터리 수명을 연장하기 위해 절전 모드가 활성화되었습니다."</string>
@@ -2292,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"애플리케이션 브랜드 이미지"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"접근성 설정 확인"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> 서비스가 내 화면을 보고 제어할 수 있습니다. 검토하려면 탭하세요."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index 697b60b5..ba12540 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -2085,17 +2085,12 @@
<string name="notification_feedback_indicator_silenced" msgid="3799442124723177262">"Бул билдирменин маанилүүлүгү Үнсүз болуп төмөндөтүлдү. Пикир билдирүү үчүн таптап коюңуз."</string>
<string name="notification_feedback_indicator_promoted" msgid="9030204303764698640">"Бул билдирменин маанилүүлүгү жогорулатылды. Пикир билдирүү үчүн таптап коюңуз."</string>
<string name="notification_feedback_indicator_demoted" msgid="8880309924296450875">"Бул билдирменин маанилүүлүгү төмөндөтүлдү. Пикир билдирүү үчүн таптап коюңуз."</string>
- <!-- no translation found for nas_upgrade_notification_title (8436359459300146555) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_content (5157550369837103337) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_enable_action (3046406808378726874) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_disable_action (3794833210043497982) -->
- <skip />
+ <string name="nas_upgrade_notification_title" msgid="8436359459300146555">"Жакшыртылган билдирмелер"</string>
+ <string name="nas_upgrade_notification_content" msgid="5157550369837103337">"Жакшыртылган билдирмелерде эми ыкчам аракеттер жана жооптор сунушталат. Android\'дин ыңгайлаштырылуучу билдирмелери колдоого алынбай калды."</string>
+ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"Макул"</string>
+ <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"Өчүрүү"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"Кененирээк"</string>
- <!-- no translation found for nas_upgrade_notification_learn_more_content (2353549817159426430) -->
- <skip />
+ <string name="nas_upgrade_notification_learn_more_content" msgid="2353549817159426430">"Android 12 версиясында ыңгайлаштырылуучу билдирмелер жакшыртылган билдирмелерге алмаштырылды. Бул функция ыкчам аракеттерди жана жоопторду көрсөтүп, билдирмелериңизди иреттейт.\n\nЖакшыртылган билдирмелер бардык билдирмелердин мазмунун, ошондой эле байланыштардын аты-жөнү жана билдирүүлөрү сыяктуу жеке маалыматты көрө алат. Ошондой эле, бул функция билдирмелерди жаап, баскычтарын басып, телефон чалууларга жооп берип жана \"Тынчымды алба\" функциясын башкара алат."</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Режимдин адаттагы билдирмеси"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Батарея кубаттоого чейин отуруп калышы мүмкүн"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Батареянын отуруп калбашы үчүн Батареяны үнөмдөгүч режими иштетилди"</string>
@@ -2292,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Колдонмонун брендинин сүрөтү"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Кирүү мүмкүнчүлүгүнүн жөндөөлөрүн текшериңиз"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> экраныңызды көрүп, көзөмөлдөй алат. Көрүү үчүн таптап коюңуз."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index f75612f..5557b60 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -2287,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"ຮູບແບຣນແອັບພລິເຄຊັນ"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"ກວດສອບການຕັ້ງຄ່າການເຂົ້າເຖິງ"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> ສາມາດເບິ່ງ ແລະ ຄວບຄຸມໜ້າຈໍຂອງທ່ານໄດ້. ແຕະເພື່ອກວດສອບ."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 88c90b7..26fd0ab 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -2151,17 +2151,12 @@
<string name="notification_feedback_indicator_silenced" msgid="3799442124723177262">"Šio pranešimo svarba sumažinta iki begarsio lygio. Palieskite, kad pateiktumėte atsiliepimą."</string>
<string name="notification_feedback_indicator_promoted" msgid="9030204303764698640">"Šio pranešimo svarba padidinta. Palieskite, kad pateiktumėte atsiliepimą."</string>
<string name="notification_feedback_indicator_demoted" msgid="8880309924296450875">"Šio pranešimo svarba sumažinta. Palieskite, kad pateiktumėte atsiliepimą."</string>
- <!-- no translation found for nas_upgrade_notification_title (8436359459300146555) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_content (5157550369837103337) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_enable_action (3046406808378726874) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_disable_action (3794833210043497982) -->
- <skip />
+ <string name="nas_upgrade_notification_title" msgid="8436359459300146555">"Patobulinti pranešimai"</string>
+ <string name="nas_upgrade_notification_content" msgid="5157550369837103337">"Siūlomi veiksmai ir atsakymai dabar teikiami patobulintais pranešimais. „Android“ prisitaikantys pranešimai nebepalaikomi."</string>
+ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"Gerai"</string>
+ <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"Išjungti"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"Sužinokite daugiau"</string>
- <!-- no translation found for nas_upgrade_notification_learn_more_content (2353549817159426430) -->
- <skip />
+ <string name="nas_upgrade_notification_learn_more_content" msgid="2353549817159426430">"12 versijos „Android“ patobulinti pranešimai pakeitė „Android“ prisitaikančius pranešimus. Ši funkcija rodo siūlomus veiksmus bei atsakymus ir tvarko jūsų pranešimus.\n\nPatobulintų pranešimų funkcija gali pasiekti pranešimų turinį, įskaitant asmens informaciją (pvz., kontaktų vardus ir pranešimus). Ši funkcija taip pat gali atsisakyti pranešimų arba į juos atsakyti, pvz., atsakyti į telefono skambučius ir valdyti netrukdymo režimą."</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Veiksmų sekos režimo informacijos pranešimas"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Akumuliatoriaus energija gali išsekti prieš įprastą įkrovimą"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Akumuliatoriaus tausojimo priemonė suaktyvinta, kad akumuliatorius veiktų ilgiau"</string>
@@ -2360,4 +2355,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Programos prekės ženklo vaizdas"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Patikrinkite prieigos nustatymus"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"„<xliff:g id="SERVICE_NAME">%s</xliff:g>“ gali peržiūrėti ir valdyti jūsų ekraną. Palieskite ir peržiūrėkite."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index c952dc2..6e09a6d 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -2118,17 +2118,12 @@
<string name="notification_feedback_indicator_silenced" msgid="3799442124723177262">"Šī paziņojuma svarīgums tika pazemināts, un paziņojums tiks rādīts bez skaņas. Lai sniegtu atsauksmes, pieskarieties."</string>
<string name="notification_feedback_indicator_promoted" msgid="9030204303764698640">"Šī paziņojuma rangs tika paaugstināts. Lai sniegtu atsauksmes, pieskarieties."</string>
<string name="notification_feedback_indicator_demoted" msgid="8880309924296450875">"Šī paziņojuma rangs tika pazemināts. Lai sniegtu atsauksmes, pieskarieties."</string>
- <!-- no translation found for nas_upgrade_notification_title (8436359459300146555) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_content (5157550369837103337) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_enable_action (3046406808378726874) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_disable_action (3794833210043497982) -->
- <skip />
+ <string name="nas_upgrade_notification_title" msgid="8436359459300146555">"Uzlabotie paziņojumi"</string>
+ <string name="nas_upgrade_notification_content" msgid="5157550369837103337">"Tagad ieteiktās darbības un atbildes nodrošina funkcija Uzlabotie paziņojumi. Android adaptīvie paziņojumi vairs netiek atbalstīti."</string>
+ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"Labi"</string>
+ <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"Izslēgt"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"Uzzināt vairāk"</string>
- <!-- no translation found for nas_upgrade_notification_learn_more_content (2353549817159426430) -->
- <skip />
+ <string name="nas_upgrade_notification_learn_more_content" msgid="2353549817159426430">"Android 12 versijā Android adaptīvos paziņojumus aizstāja funkcija “Uzlabotie paziņojumi”. Šī funkcija parāda ieteiktās darbības un atbildes, kā arī kārto jūsu paziņojumus.\n\nFunkcija “Uzlabotie paziņojumi” var piekļūt paziņojumu saturam, tostarp personas informācijai, piemēram, kontaktpersonu vārdiem un ziņojumiem. Šī funkcija var arī noraidīt paziņojumus vai atbildēt uz tiem, piemēram, atbildēt uz tālruņa zvaniem vai pārvaldīt funkciju Netraucēt."</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Informatīvs paziņojums par akumulatoru"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Akumulators var izlādēties pirms parastā uzlādes laika"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Aktivizēts akumulatora enerģijas taupīšanas režīms, lai palielinātu akumulatora darbības ilgumu"</string>
@@ -2326,4 +2321,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Lietojumprogrammas zīmola attēls"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Pārbaudiet piekļuves iestatījumus"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"Pakalpojums <xliff:g id="SERVICE_NAME">%s</xliff:g> var skatīt un kontrolēt jūsu ekrānu. Pieskarieties, lai to pārskatītu."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 82ac5828..4d6b252 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -2287,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Слика за брендирање на апликацијата"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Проверете ги поставките за пристап"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> може да го прегледува и контролира вашиот екран. Допрете за да прегледате."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index e6ff7ea..a8bda14 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -2085,17 +2085,12 @@
<string name="notification_feedback_indicator_silenced" msgid="3799442124723177262">"ഈ അറിയിപ്പിനെ നിശബ്ദമാക്കി തരം താഴ്ത്തി. ഫീഡ്ബാക്ക് നൽകാൻ ടാപ്പ് ചെയ്യുക."</string>
<string name="notification_feedback_indicator_promoted" msgid="9030204303764698640">"ഈ അറിയിപ്പിന് ഉയർന്ന റാങ്ക് നൽകി. ഫീഡ്ബാക്ക് നൽകാൻ ടാപ്പ് ചെയ്യുക."</string>
<string name="notification_feedback_indicator_demoted" msgid="8880309924296450875">"ഈ അറിയിപ്പിന് താഴ്ന്ന റാങ്ക് നൽകി. ഫീഡ്ബാക്ക് നൽകാൻ ടാപ്പ് ചെയ്യുക."</string>
- <!-- no translation found for nas_upgrade_notification_title (8436359459300146555) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_content (5157550369837103337) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_enable_action (3046406808378726874) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_disable_action (3794833210043497982) -->
- <skip />
+ <string name="nas_upgrade_notification_title" msgid="8436359459300146555">"മെച്ചപ്പെടുത്തിയ അറിയിപ്പുകൾ"</string>
+ <string name="nas_upgrade_notification_content" msgid="5157550369837103337">"നിർദ്ദേശിക്കുന്ന പ്രവർത്തനങ്ങളും മറുപടികളും, \'മെച്ചപ്പെടുത്തിയ അറിയിപ്പുകൾ\' ഫീച്ചറാണ് ഇപ്പോൾ നൽകുന്നത്. Android അഡാപ്റ്റീവ് അറിയിപ്പുകൾക്ക് ഇനി പിന്തുണയില്ല."</string>
+ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"ശരി"</string>
+ <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"ഓഫാക്കുക"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"കൂടുതലറിയുക"</string>
- <!-- no translation found for nas_upgrade_notification_learn_more_content (2353549817159426430) -->
- <skip />
+ <string name="nas_upgrade_notification_learn_more_content" msgid="2353549817159426430">"Android 12-ൽ Android അഡാപ്റ്റീവ് അറിയിപ്പുകൾക്ക് പകരം മെച്ചപ്പെടുത്തിയ അറിയിപ്പുകൾ ഉൾപ്പെടുത്തിയിരിക്കുന്നു. നിർദ്ദേശിക്കുന്ന പ്രവർത്തനങ്ങളും മറുപടികളും കാണിക്കുന്നതിനൊപ്പം ഈ ഫീച്ചർ നിങ്ങളുടെ അറിയിപ്പുകൾ ഓർഗനൈസ് ചെയ്യുന്നു.\n\nമെച്ചപ്പെടുത്തിയ അറിയിപ്പുകൾക്ക്, കോൺടാക്റ്റ് പേരുകളും സന്ദേശങ്ങളും പോലുള്ള വ്യക്തിപരമായ വിവരങ്ങൾ ഉൾപ്പെടെയുള്ള അറിയിപ്പ് ഉള്ളടക്കം ആക്സസ് ചെയ്യാനാകും. ഫോൺ കോളുകൾക്ക് മറുപടി നൽകുക, \'ശല്യപ്പെടുത്തരുത്\' നിയന്ത്രിക്കുക എന്നിവ പോലെ, അറിയിപ്പുകൾ ഡിസ്മിസ് ചെയ്യാനും അവയ്ക്ക് മറുപടി നൽകാനും ഈ ഫീച്ചറിന് കഴിയും."</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"ദിനചര്യ മോഡ് വിവരത്തെ കുറിച്ചുള്ള അറിയിപ്പ്"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"സാധാരണയുള്ളതിലും നേരത്തെ ബാറ്ററിയുടെ ചാർജ് തീർന്നേക്കാം"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"ബാറ്ററി ലൈഫ് വര്ദ്ധിപ്പിക്കാൻ, ബാറ്ററി ലാഭിക്കൽ സജീവമാക്കി"</string>
@@ -2292,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"അപ്ലിക്കേഷൻ ബ്രാൻഡിംഗ് ഇമേജ്"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"ആക്സസ് ക്രമീകരണം പരിശോധിക്കുക"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> എന്നതിന് നിങ്ങളുടെ സ്ക്രീൻ കാണാനും നിയന്ത്രിക്കാനും കഴിയും. അവലോകനം ചെയ്യുന്നതിന് ടാപ്പ് ചെയ്യുക."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 5064068..99bd674 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -2085,17 +2085,12 @@
<string name="notification_feedback_indicator_silenced" msgid="3799442124723177262">"Энэ мэдэгдлийг Чимээгүй болгож зэргийг нь бууруулсан байна. Санал хүсэлт өгөхийн тулд товшино уу."</string>
<string name="notification_feedback_indicator_promoted" msgid="9030204303764698640">"Энэ мэдэгдлийг дээгүүр зэрэглэсэн байна. Санал хүсэлт өгөхийн тулд товшино уу."</string>
<string name="notification_feedback_indicator_demoted" msgid="8880309924296450875">"Энэ мэдэгдлийг доогуур зэрэглэсэн байна. Санал хүсэлт өгөхийн тулд товшино уу."</string>
- <!-- no translation found for nas_upgrade_notification_title (8436359459300146555) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_content (5157550369837103337) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_enable_action (3046406808378726874) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_disable_action (3794833210043497982) -->
- <skip />
+ <string name="nas_upgrade_notification_title" msgid="8436359459300146555">"Сайжруулсан мэдэгдэл"</string>
+ <string name="nas_upgrade_notification_content" msgid="5157550369837103337">"Санал болгосон үйлдлүүд болон хариунуудыг одоо сайржуулсан мэдэгдлээр олгоно. Android-н Орчинтой тохирсон мэдэгдлийг цаашид дэмжихээ больсон."</string>
+ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"OK"</string>
+ <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"Унтраах"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"Нэмэлт мэдээлэл авах"</string>
- <!-- no translation found for nas_upgrade_notification_learn_more_content (2353549817159426430) -->
- <skip />
+ <string name="nas_upgrade_notification_learn_more_content" msgid="2353549817159426430">"Сайжруулсан мэдэгдэл нь Android 12 дахь Android-н Орчинтой тохирсон мэдэгдлийг орлосон. Энэ онцлог нь санал болгосон үйлдлүүд болон хариунуудыг харуулж, таны мэдэгдлийг цэгцэлнэ.\n\nСайжруулсан мэдэгдэл нь харилцагчийн нэр, мессеж зэрэг хувийн мэдээллийг оруулаад мэдэгдлийн контентод хандах боломжтой. Энэ онцлог мөн утасны дуудлагад хариулах болон Бүү саад бол горимыг хянах зэргээр мэдэгдлийг хаах эсвэл түүнд хариулах боломжтой."</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Хэвшлийн горимын мэдээллийн мэдэгдэл"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Батарей ихэвчлэн цэнэглэдэг хугацаанаас өмнө дуусаж болзошгүй"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Батарейн ажиллах хугацааг уртасгахын тулд Батарей хэмнэгчийг идэвхжүүллээ"</string>
@@ -2292,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Аппын брэнд зураг"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Хандалтын тохиргоог шалгана уу"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> таны дэлгэцийг харах болон хянах боломжтой. Хянахын тулд товшино уу."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index ba20d59..b3b1d13 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -2287,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"अॅप्लिकेशन ब्रॅंडिंग इमेज"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"अॅक्सेसशी संबंधित सेटिंग्ज तपासा"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> हे तुमची स्क्रीन पाहू शकते आणि नियंत्रित करू शकते. परीक्षण करण्यासाठी टॅप करा."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 4d55195..937b31f 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -2287,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Imej jenama aplikasi"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Semak tetapan akses"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> boleh melihat dan mengawal skrin anda. Ketik untuk membuat semakan."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index 43ed918..983de0e 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -2085,17 +2085,12 @@
<string name="notification_feedback_indicator_silenced" msgid="3799442124723177262">"ဤအကြောင်းကြားချက်ကို \'အသံတိတ်ခြင်း\' သို့ ပြန်ချိန်ညှိထားသည်။ အကြံပြုချက်ပေးရန် တို့ပါ။"</string>
<string name="notification_feedback_indicator_promoted" msgid="9030204303764698640">"ဤအကြောင်းကြားချက်ကို အဆင့်တိုးထားသည်။ အကြံပြုချက်ပေးရန် တို့ပါ။"</string>
<string name="notification_feedback_indicator_demoted" msgid="8880309924296450875">"ဤအကြောင်းကြားချက်ကို အဆင့်လျှော့ထားသည်။ အကြံပြုချက်ပေးရန် တို့ပါ။"</string>
- <!-- no translation found for nas_upgrade_notification_title (8436359459300146555) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_content (5157550369837103337) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_enable_action (3046406808378726874) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_disable_action (3794833210043497982) -->
- <skip />
+ <string name="nas_upgrade_notification_title" msgid="8436359459300146555">"အဆင့်မြင့် အကြောင်းကြားချက်များ"</string>
+ <string name="nas_upgrade_notification_content" msgid="5157550369837103337">"အကြံပြုထားသော လုပ်ဆောင်ချက်နှင့် ပြန်စာများကို အဆင့်မြင့် အကြောင်းကြားချက်များဖြင့် ယခု ပံ့ပိုးပေးသည်။ ‘Android အလိုက်သင့် အကြောင်းကြားချက်များ’ ကို ပံ့ပိုးမထားတော့ပါ။"</string>
+ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"OK"</string>
+ <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"ပိတ်ရန်"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"ပိုမိုလေ့လာရန်"</string>
- <!-- no translation found for nas_upgrade_notification_learn_more_content (2353549817159426430) -->
- <skip />
+ <string name="nas_upgrade_notification_learn_more_content" msgid="2353549817159426430">"Android 12 တွင် ‘Android အလိုက်သင့် အကြောင်းကြားချက်များ’ ကို အဆင့်မြင့် အကြောင်းကြားချက်များဖြင့် အစားထိုးထားသည်။ ဤဝန်ဆောင်မှုက အကြံပြုထားသော လုပ်ဆောင်ချက်နှင့် ပြန်စာများကို ပြပေးပြီး သင်၏အကြောင်းကြားချက်များကို စီစဉ်ပေးသည်။\n\nအဆင့်မြင့် အကြောင်းကြားချက်များက အဆက်အသွယ်အမည်နှင့် မက်ဆေ့ဂျ်များကဲ့သို့ ကိုယ်ရေးကိုယ်တာအချက်လက်များ အပါအဝင် အကြောင်းကြားချက် အကြောင်းအရာကို သုံးနိုင်သည်။ ဤဝန်ဆောင်မှုက ဖုန်းခေါ်ဆိုမှုများ ဖြေခြင်းနှင့် ‘မနှောင့်ယှက်ရ’ ကို ထိန်းချုပ်ခြင်းကဲ့သို့ အကြောင်းကြားချက်များကို ပယ်နိုင်သည် (သို့) တုံ့ပြန်နိုင်သည်။"</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"ပုံမှန်မုဒ်အတွက် အချက်အလက်ပြသည့် အကြောင်းကြားချက်"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"ပုံမှန်အားသွင်းမှုမပြုလုပ်မီ ဘက်ထရီကုန်သွားနိုင်သည်"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"ဘက်ထရီသက်တမ်းကို တိုးမြှင့်ရန် \'ဘက်ထရီအားထိန်း\' စတင်ပြီးပါပြီ"</string>
@@ -2292,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"အပလီကေးရှင်း ကုန်အမှတ်တံဆိပ်ပုံ"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"အသုံးပြုခွင့် ဆက်တင်များကို စစ်ဆေးပါ"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> က သင့်ဖန်သားပြင်ကို ကြည့်ရှုပြီး ထိန်းချုပ်နိုင်သည်။ ပြန်ကြည့်ရန် တို့ပါ။"</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 5baea2c..20c49d5 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -2287,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Merkevareprofilen til appen"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Sjekk tilgangsinnstillingene"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> kan se og kontrollere skjermen. Trykk for å gjennomgå."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index 5c9382a..d4f3083 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -1820,8 +1820,7 @@
<string name="mediasize_japanese_kahu" msgid="7290232592648122042">"Kahu"</string>
<string name="mediasize_japanese_kaku2" msgid="7477551750461028312">"Kaku2"</string>
<string name="mediasize_japanese_you4" msgid="5552111912684384833">"You4"</string>
- <!-- no translation found for mediasize_japanese_l (1326765321473431817) -->
- <skip />
+ <string name="mediasize_japanese_l" msgid="1326765321473431817">"L"</string>
<string name="mediasize_unknown_portrait" msgid="3817016220446495613">"अज्ञात चित्र"</string>
<string name="mediasize_unknown_landscape" msgid="1584741567225095325">"अज्ञात परिदृश्य"</string>
<string name="write_fail_reason_cancelled" msgid="2344081488493969190">"रद्द गरियो"</string>
@@ -1865,10 +1864,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 (750683025714899363) -->
- <skip />
- <!-- no translation found for battery_saver_description (5693741424234005958) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="750683025714899363">"ब्याट्री सेभरले अँध्यारो थिम अन गर्छ र ब्याकग्राउन्डमा हुने क्रियाकलाप, केही भिजुअल इफेक्ट र निश्चित सुविधाहरू अफ गर्छ वा सीमित रूपमा मात्र चल्न दिन्छ।\n\n"<annotation id="url">"थप जान्नुहोस्"</annotation></string>
+ <string name="battery_saver_description" msgid="5693741424234005958">"ब्याट्री सेभरले अँध्यारो थिम अन गर्छ र ब्याकग्राउन्डमा हुने क्रियाकलाप, केही भिजुअल इफेक्ट र निश्चित सुविधाहरू अफ गर्छ वा सीमित रूपमा मात्र चल्न दिन्छ।"</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>
@@ -2096,8 +2093,7 @@
<skip />
<!-- no translation found for nas_upgrade_notification_disable_action (3794833210043497982) -->
<skip />
- <!-- no translation found for nas_upgrade_notification_learn_more_action (7011130656195423947) -->
- <skip />
+ <string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"थप जान्नुहोस्"</string>
<!-- no translation found for nas_upgrade_notification_learn_more_content (2353549817159426430) -->
<skip />
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"दिनचर्या मोडको जानकारीमूलक सूचना"</string>
@@ -2296,4 +2292,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"एपको ब्रान्डिङ फोटो"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"हेराइ र नियन्त्रणसम्बन्धी सेटिङ जाँच्नुहोस्"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> तपाईंको स्क्रिन हेर्न र नियन्त्रण गर्न सक्छ। सेटिङ मिलाउन ट्याप गर्नुहोस्।"</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 2dab66e..f2533b3 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -2287,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Merkafbeelding voor app"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Toegangsinstellingen checken"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> kan je scherm bekijken en bedienen. Tik om te checken."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index 8a63f06..5aa16e7 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -1820,8 +1820,7 @@
<string name="mediasize_japanese_kahu" msgid="7290232592648122042">"Kahu"</string>
<string name="mediasize_japanese_kaku2" msgid="7477551750461028312">"Kaku2"</string>
<string name="mediasize_japanese_you4" msgid="5552111912684384833">"You4"</string>
- <!-- no translation found for mediasize_japanese_l (1326765321473431817) -->
- <skip />
+ <string name="mediasize_japanese_l" msgid="1326765321473431817">"L"</string>
<string name="mediasize_unknown_portrait" msgid="3817016220446495613">"ଅଜଣା ପୋର୍ଟ୍ରେଟ୍"</string>
<string name="mediasize_unknown_landscape" msgid="1584741567225095325">"ଅଜଣା ଲ୍ୟାଣ୍ଡସ୍କେପ୍"</string>
<string name="write_fail_reason_cancelled" msgid="2344081488493969190">"ବାତିଲ୍ କରାଗଲା"</string>
@@ -1865,10 +1864,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 (750683025714899363) -->
- <skip />
- <!-- no translation found for battery_saver_description (5693741424234005958) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="750683025714899363">"ବ୍ୟାଟେରୀ ସେଭର୍ ଗାଢ଼ା ଥିମକୁ ଚାଲୁ କରେ ଏବଂ ପୃଷ୍ଠପଟ କାର୍ଯ୍ୟକଳାପ, କିଛି ଭିଜୁଆଲ୍ ଇଫେକ୍ଟ ଏବଂ କିଛି ଫିଚରଗୁଡ଼ିକୁ ସୀମିତ କିମ୍ବା ବନ୍ଦ କରେ।\n\n"<annotation id="url">"ଅଧିକ ଜାଣନ୍ତୁ"</annotation></string>
+ <string name="battery_saver_description" msgid="5693741424234005958">"ବ୍ୟାଟେରୀ ସେଭର୍ ଗାଢ଼ା ଥିମକୁ ଚାଲୁ କରେ ଏବଂ ପୃଷ୍ଠପଟ କାର୍ଯ୍ୟକଳାପ, କିଛି ଭିଜୁଆଲ୍ ଇଫେକ୍ଟ ଏବଂ କିଛି ଫିଚରଗୁଡ଼ିକୁ ସୀମିତ କିମ୍ବା ବନ୍ଦ କରେ।"</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>
@@ -2088,17 +2085,12 @@
<string name="notification_feedback_indicator_silenced" msgid="3799442124723177262">"ଏହି ବିଜ୍ଞପ୍ତିକୁ ନୀରବ ଭାବେ ଡିମୋଟ୍ କରାଯାଇଛି। ମତାମତ ପ୍ରଦାନ କରିବାକୁ ଟାପ୍ କରନ୍ତୁ।"</string>
<string name="notification_feedback_indicator_promoted" msgid="9030204303764698640">"ଏହି ବିଜ୍ଞପ୍ତିର ରେଙ୍କ ଉପରକୁ କରାଯାଇଛି। ମତାମତ ପ୍ରଦାନ କରିବାକୁ ଟାପ୍ କରନ୍ତୁ।"</string>
<string name="notification_feedback_indicator_demoted" msgid="8880309924296450875">"ଏହି ବିଜ୍ଞପ୍ତିର ରେଙ୍କ ତଳକୁ କରାଯାଇଛି। ମତାମତ ପ୍ରଦାନ କରିବାକୁ ଟାପ୍ କରନ୍ତୁ।"</string>
- <!-- no translation found for nas_upgrade_notification_title (8436359459300146555) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_content (5157550369837103337) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_enable_action (3046406808378726874) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_disable_action (3794833210043497982) -->
- <skip />
+ <string name="nas_upgrade_notification_title" msgid="8436359459300146555">"ଉନ୍ନତ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ"</string>
+ <string name="nas_upgrade_notification_content" msgid="5157550369837103337">"ପ୍ରସ୍ତାବିତ କାର୍ଯ୍ୟ ଏବଂ ପ୍ରତ୍ୟୁତ୍ତରଗୁଡ଼ିକ ବର୍ତ୍ତମାନ ଉନ୍ନତ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ ମାଧ୍ୟମରେ ପ୍ରଦାନ କରାଯାଉଛି। Android ଆଡେପ୍ଟିଭ୍ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ ଆଉ ସମର୍ଥିତ ନୁହେଁ।"</string>
+ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"ଠିକ୍ ଅଛି"</string>
+ <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"ବନ୍ଦ କରନ୍ତୁ"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"ଅଧିକ ଜାଣନ୍ତୁ"</string>
- <!-- no translation found for nas_upgrade_notification_learn_more_content (2353549817159426430) -->
- <skip />
+ <string name="nas_upgrade_notification_learn_more_content" msgid="2353549817159426430">"Android 12ରେ Android ଆଡେପ୍ଟିଭ୍ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକୁ ଉନ୍ନତ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକରେ ପରିବର୍ତ୍ତନ କରାଯାଇଛି। ଏହି ଫିଚର୍ ପ୍ରସ୍ତାବିତ କାର୍ଯ୍ୟ ଏବଂ ପ୍ରତ୍ୟୁତ୍ତରଗୁଡ଼ିକୁ ଦେଖାଏ ଏବଂ ଆପଣଙ୍କ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକୁ ବ୍ୟବସ୍ଥିତ କରେ।\n\nଉନ୍ନତ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ ଯୋଗାଯୋଗ ନାମ ଏବଂ ମେସେଜଗୁଡ଼ିକ ପରି ବ୍ୟକ୍ତିଗତ ସୂଚନା ସମେତ ବିଜ୍ଞପ୍ତିର ବିଷୟବସ୍ତୁକୁ ଆକ୍ସେସ୍ କରିପାରିବ। ଏହି ଫିଚର୍ ଫୋନ୍ କଲଗୁଡ଼ିକର ଉତ୍ତର ଦେବା ଏବଂ \'ବିରକ୍ତ କରନ୍ତୁ ନାହିଁ\'କୁ ନିୟନ୍ତ୍ରଣ କରିବା ପରି, ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକୁ ମଧ୍ୟ ଖାରଜ କରିପାରିବ କିମ୍ବା ସେଗୁଡ଼ିକର ଉତ୍ତର ଦେଇପାରିବ।"</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"ନିୟମିତ ମୋଡ୍ ସୂଚନା ବିଜ୍ଞପ୍ତି"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"ସାଧାରଣ ଭାବରେ ଚାର୍ଜ୍ କରିବା ପୂର୍ବରୁ ବ୍ୟାଟେରୀ ସରିଯାଇପାରେ"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"ବ୍ୟାଟେରୀର ସମୟକୁ ବଢ଼ାଇବା ପାଇଁ ବ୍ୟଟେରୀ ସେଭର୍କୁ କାର୍ଯ୍ୟକାରୀ କରାଯାଇଛି"</string>
@@ -2295,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"ଆପ୍ଲିକେସନ୍ ବ୍ରାଣ୍ଡିଂ ଛବି"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"ଆକ୍ସେସ୍ ସେଟିଂସକୁ ଯାଞ୍ଚ କରନ୍ତୁ"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> ଆପଣଙ୍କ ସ୍କ୍ରିନକୁ ଦେଖିପାରିବ ଏବଂ ନିୟନ୍ତ୍ରଣ କରିପାରିବ। ସମୀକ୍ଷା କରିବାକୁ ଟାପ୍ କରନ୍ତୁ।"</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 1711a88..6cc4f19 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -1820,8 +1820,7 @@
<string name="mediasize_japanese_kahu" msgid="7290232592648122042">"Kahu"</string>
<string name="mediasize_japanese_kaku2" msgid="7477551750461028312">"Kaku2"</string>
<string name="mediasize_japanese_you4" msgid="5552111912684384833">"You4"</string>
- <!-- no translation found for mediasize_japanese_l (1326765321473431817) -->
- <skip />
+ <string name="mediasize_japanese_l" msgid="1326765321473431817">"L"</string>
<string name="mediasize_unknown_portrait" msgid="3817016220446495613">"ਅਗਿਆਤ ਪੋਰਟਰੇਟ"</string>
<string name="mediasize_unknown_landscape" msgid="1584741567225095325">"ਅਗਿਆਤ ਲੈਂਡਸਕੇਪ"</string>
<string name="write_fail_reason_cancelled" msgid="2344081488493969190">"ਰੱਦ ਕੀਤਾ ਗਿਆ"</string>
@@ -1865,10 +1864,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 (750683025714899363) -->
- <skip />
- <!-- no translation found for battery_saver_description (5693741424234005958) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="750683025714899363">"ਬੈਟਰੀ ਸੇਵਰ ਗੂੜ੍ਹੇ ਥੀਮ ਨੂੰ ਚਾਲੂ ਕਰਦਾ ਹੈ ਅਤੇ ਬੈਕਗ੍ਰਾਊਂਡ ਸਰਗਰਮੀ, ਕੁਝ ਦ੍ਰਿਸ਼ਟੀਗਤ ਪ੍ਰਭਾਵਾਂ ਅਤੇ ਕੁਝ ਖਾਸ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਨੂੰ ਸੀਮਤ ਜਾਂ ਬੰਦ ਕਰਦਾ ਹੈ।\n\n"<annotation id="url">"ਹੋਰ ਜਾਣੋ"</annotation></string>
+ <string name="battery_saver_description" msgid="5693741424234005958">"ਬੈਟਰੀ ਸੇਵਰ ਗੂੜ੍ਹੇ ਥੀਮ ਨੂੰ ਚਾਲੂ ਕਰਦਾ ਹੈ ਅਤੇ ਬੈਕਗ੍ਰਾਊਂਡ ਸਰਗਰਮੀ, ਕੁਝ ਦ੍ਰਿਸ਼ਟੀਗਤ ਪ੍ਰਭਾਵਾਂ ਅਤੇ ਕੁਝ ਖਾਸ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਨੂੰ ਸੀਮਤ ਜਾਂ ਬੰਦ ਕਰਦਾ ਹੈ।"</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>
@@ -2088,17 +2085,12 @@
<string name="notification_feedback_indicator_silenced" msgid="3799442124723177262">"ਇਸ ਸੂਚਨਾ ਦਾ ਦਰਜਾ ਘਟਾ ਕੇ ਸ਼ਾਂਤ \'ਤੇ ਸੈੱਟ ਕੀਤਾ ਗਿਆ। ਵਿਚਾਰ ਮੁਹੱਈਆ ਕਰਵਾਉਣ ਲਈ ਟੈਪ ਕਰੋ।"</string>
<string name="notification_feedback_indicator_promoted" msgid="9030204303764698640">"ਇਸ ਸੂਚਨਾ ਦਾ ਦਰਜਾ ਵਧਾ ਦਿੱਤਾ ਗਿਆ। ਵਿਚਾਰ ਮੁਹੱਈਆ ਕਰਵਾਉਣ ਲਈ ਟੈਪ ਕਰੋ।"</string>
<string name="notification_feedback_indicator_demoted" msgid="8880309924296450875">"ਇਸ ਸੂਚਨਾ ਦਾ ਦਰਜਾ ਘਟਾ ਦਿੱਤਾ ਗਿਆ। ਵਿਚਾਰ ਮੁਹੱਈਆ ਕਰਵਾਉਣ ਲਈ ਟੈਪ ਕਰੋ।"</string>
- <!-- no translation found for nas_upgrade_notification_title (8436359459300146555) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_content (5157550369837103337) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_enable_action (3046406808378726874) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_disable_action (3794833210043497982) -->
- <skip />
+ <string name="nas_upgrade_notification_title" msgid="8436359459300146555">"ਵਿਸਤ੍ਰਿਤ ਸੂਚਨਾਵਾਂ"</string>
+ <string name="nas_upgrade_notification_content" msgid="5157550369837103337">"ਸੁਝਾਈਆਂ ਗਈਆਂ ਕਾਰਵਾਈਆਂ ਅਤੇ ਜਵਾਬ ਹੁਣ ਵਿਸਤ੍ਰਿਤ ਸੂਚਨਾਵਾਂ ਵੱਲੋਂ ਮੁਹੱਈਆ ਕਰਵਾਏ ਜਾਂਦੇ ਹਨ। Android ਅਡੈਪਟਿਵ ਸੂਚਨਾਵਾਂ ਹੁਣ ਸਮਰਥਿਤ ਨਹੀਂ ਹਨ।"</string>
+ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"ਠੀਕ ਹੈ"</string>
+ <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"ਬੰਦ ਕਰੋ"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"ਹੋਰ ਜਾਣੋ"</string>
- <!-- no translation found for nas_upgrade_notification_learn_more_content (2353549817159426430) -->
- <skip />
+ <string name="nas_upgrade_notification_learn_more_content" msgid="2353549817159426430">"Android 12 ਵਿੱਚ ਵਿਸਤ੍ਰਿਤ ਸੂਚਨਾਵਾਂ ਨੂੰ Android ਅਡੈਪਟਿਵ ਸੂਚਨਾਵਾਂ ਨਾਲ ਬਦਲ ਦਿੱਤਾ ਗਿਆ। ਇਹ ਵਿਸ਼ੇਸ਼ਤਾ ਸੁਝਾਈਆਂ ਗਈਆਂ ਕਾਰਵਾਈਆਂ ਅਤੇ ਜਵਾਬ ਦਿਖਾਉਂਦੀ ਹੈ ਅਤੇ ਤੁਹਾਡੀਆਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਵਿਵਸਥਿਤ ਕਰਦੀ ਹੈ।\n\nਵਿਸਤ੍ਰਿਤ ਸੂਚਨਾਵਾਂ ਸੂਚਨਾ ਸਮੱਗਰੀ ਤੱਕ ਪਹੁੰਚ ਕਰ ਸਕਦੀਆਂ ਹਨ, ਜਿਸ ਵਿੱਚ ਸੰਪਰਕ ਨਾਮ ਅਤੇ ਸੁਨੇਹਿਆਂ ਵਰਗੀ ਨਿੱਜੀ ਜਾਣਕਾਰੀ ਸ਼ਾਮਲ ਹੈ। ਇਹ ਵਿਸ਼ੇਸ਼ਤਾ ਸੂਚਨਾਵਾਂ ਨੂੰ ਖਾਰਜ ਵੀ ਕਰ ਸਕਦੀ ਹੈ ਜਾਂ ਸੂਚਨਾਵਾਂ ਦਾ ਜਵਾਬ ਵੀ ਦੇ ਸਕਦੀ ਹੈ, ਜਿਵੇਂ ਕਿ ਫ਼ੋਨ ਕਾਲਾਂ ਦਾ ਜਵਾਬ ਦੇਣਾ ਅਤੇ \'ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ\' ਨੂੰ ਕੰਟਰੋਲ ਕਰਨਾ।"</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"ਨਿਯਮਬੱਧ ਮੋਡ ਦੀ ਜਾਣਕਾਰੀ ਵਾਲੀ ਸੂਚਨਾ"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"ਬੈਟਰੀ ਚਾਰਜ ਕਰਨ ਦੇ ਮਿੱਥੇ ਸਮੇਂ ਤੋਂ ਪਹਿਲਾਂ ਸ਼ਾਇਦ ਬੈਟਰੀ ਖਤਮ ਹੋ ਜਾਵੇ"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"ਬੈਟਰੀ ਲਾਈਫ਼ ਵਧਾਉਣ ਲਈ ਬੈਟਰੀ ਸੇਵਰ ਚਾਲੂ ਕੀਤਾ ਗਿਆ"</string>
@@ -2295,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"ਐਪਲੀਕੇਸ਼ਨ ਦਾ ਬ੍ਰਾਂਡ ਵਾਲਾ ਚਿੱਤਰ"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"ਪਹੁੰਚ ਸੈਟਿੰਗਾਂ ਦੀ ਜਾਂਚ ਕਰੋ"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> ਸੇਵਾ ਤੁਹਾਡੀ ਸਕ੍ਰੀਨ ਨੂੰ ਦੇਖ ਅਤੇ ਕੰਟਰੋਲ ਕਰ ਸਕਦੀ ਹੈ। ਸਮੀਖਿਆ ਲਈ ਟੈਪ ਕਰੋ।"</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index bc11c37..69d9b1c 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -2151,17 +2151,12 @@
<string name="notification_feedback_indicator_silenced" msgid="3799442124723177262">"To powiadomienie zostało zmienione na Ciche. Kliknij, by przesłać opinię."</string>
<string name="notification_feedback_indicator_promoted" msgid="9030204303764698640">"Podniesiono ważność tego powiadomienia. Kliknij, by przesłać opinię."</string>
<string name="notification_feedback_indicator_demoted" msgid="8880309924296450875">"Obniżono ważność tego powiadomienia. Kliknij, by przesłać opinię."</string>
- <!-- no translation found for nas_upgrade_notification_title (8436359459300146555) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_content (5157550369837103337) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_enable_action (3046406808378726874) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_disable_action (3794833210043497982) -->
- <skip />
+ <string name="nas_upgrade_notification_title" msgid="8436359459300146555">"Ulepszone powiadomienia"</string>
+ <string name="nas_upgrade_notification_content" msgid="5157550369837103337">"Sugerowane działania i odpowiedzi pojawiają się teraz w ulepszonych powiadomieniach. Powiadomienia adaptacyjne w Androidzie nie są już obsługiwane."</string>
+ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"OK"</string>
+ <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"Wyłącz"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"Więcej informacji"</string>
- <!-- no translation found for nas_upgrade_notification_learn_more_content (2353549817159426430) -->
- <skip />
+ <string name="nas_upgrade_notification_learn_more_content" msgid="2353549817159426430">"W Androidzie 12 ulepszone powiadomienia zastąpiły powiadomienia adaptacyjne. Ta funkcja pokazuje sugerowane działania i odpowiedzi oraz porządkuje powiadomienia.\n\nUlepszone powiadomienia mogą czytać wszystkie powiadomienia, w tym dane osobowe takie jak nazwy kontaktów i treść wiadomości. Funkcja może też zamykać powiadomienia oraz reagować na nie, np. odbierać połączenia telefoniczne i sterować trybem Nie przeszkadzać."</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Powiadomienie z informacją o trybie rutynowym"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Bateria może się wyczerpać przed zwykłą porą ładowania"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Włączono Oszczędzanie baterii, by wydłużyć czas pracy na baterii"</string>
@@ -2360,4 +2355,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Wizerunek marki aplikacji"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Sprawdź ustawienia dostępu"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"Usługa <xliff:g id="SERVICE_NAME">%s</xliff:g> może wyświetlać i kontrolować ekran. Kliknij, aby sprawdzić."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index dd1ebb6..412bf86 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -2287,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Imagem da marca do aplicativo"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Confira as configurações de acesso"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"O serviço <xliff:g id="SERVICE_NAME">%s</xliff:g> pode ver e controlar sua tela. Toque para revisar."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 3b0a5ca..ec7bba7 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -2287,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Imagem de branding da aplicação."</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Verifique as definições de acesso"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"O serviço <xliff:g id="SERVICE_NAME">%s</xliff:g> pode ver e controlar o seu ecrã. Toque para rever."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index dd1ebb6..412bf86 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -2287,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Imagem da marca do aplicativo"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Confira as configurações de acesso"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"O serviço <xliff:g id="SERVICE_NAME">%s</xliff:g> pode ver e controlar sua tela. Toque para revisar."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index f064932..1104832 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -2118,17 +2118,12 @@
<string name="notification_feedback_indicator_silenced" msgid="3799442124723177262">"Notificarea a fost mutată în jos la Silențioasă. Atingeți pentru a oferi feedback."</string>
<string name="notification_feedback_indicator_promoted" msgid="9030204303764698640">"Notificarea a fost mutată la un nivel superior. Atingeți pentru a oferi feedback."</string>
<string name="notification_feedback_indicator_demoted" msgid="8880309924296450875">"Notificarea a fost mutată la un nivel inferior. Atingeți pentru a oferi feedback."</string>
- <!-- no translation found for nas_upgrade_notification_title (8436359459300146555) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_content (5157550369837103337) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_enable_action (3046406808378726874) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_disable_action (3794833210043497982) -->
- <skip />
+ <string name="nas_upgrade_notification_title" msgid="8436359459300146555">"Notificări optimizate"</string>
+ <string name="nas_upgrade_notification_content" msgid="5157550369837103337">"Acțiunile și răspunsurile sugerate sunt acum trimise prin notificări optimizate. Notificările adaptive Android nu mai sunt acceptate."</string>
+ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"OK"</string>
+ <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"Dezactivați"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"Aflați mai multe"</string>
- <!-- no translation found for nas_upgrade_notification_learn_more_content (2353549817159426430) -->
- <skip />
+ <string name="nas_upgrade_notification_learn_more_content" msgid="2353549817159426430">"Notificările optimizate au înlocuit Notificările adaptive Android de pe Android 12. Această funcție afișează acțiuni și răspunsuri sugerate și vă organizează notificările.\n\nNotificările optimizate pot accesa conținutul notificărilor, inclusiv informații cu caracter personal, precum mesajele și numele persoanelor de contact. În plus, funcția poate să închidă sau să răspundă la notificări, de exemplu, să răspundă la apeluri telefonice și să gestioneze opțiunea Nu deranja."</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Notificare pentru informații despre modul Rutină"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Bateria se poate descărca înainte de încărcarea obișnuită"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Economisirea bateriei este activată pentru a prelungi durata de funcționare a bateriei"</string>
@@ -2326,4 +2321,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Imaginea de branding a aplicației"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Verificați setările pentru acces"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> poate să vadă și să vă controleze ecranul. Atingeți pentru a examina."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 2e9c749..b491017 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -2355,4 +2355,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Образ бренда приложения"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Проверьте настройки доступа"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> просматривать и контролировать то, что отображается на вашем экране. Нажмите здесь, чтобы узнать больше."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index e98c547..7e5066c 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -2287,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"යෙදුම් සන්නම් කිරීමේ රූපය"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"ප්රවේශ සැකසීම් පරීක්ෂා කරන්න"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> හට ඔබගේ තිරය බැලීමට සහ පාලනය කිරීමට හැකිය. සමාලෝචනය කිරීමට තට්ටු කරන්න."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 6a68397..6f15130 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -2355,4 +2355,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Imidž značky aplikácie"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Kontrola nastavení prístupu"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> môže zobraziť a ovládať vašu obrazovku. Skontrolujte to klepnutím."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 5759f6ad..b128fab 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -2151,17 +2151,12 @@
<string name="notification_feedback_indicator_silenced" msgid="3799442124723177262">"To obvestilo je bilo uvrščeno nižje – med obvestila brez zvoka. Dotaknite se, če želite poslati povratne informacije."</string>
<string name="notification_feedback_indicator_promoted" msgid="9030204303764698640">"To obvestilo je bilo uvrščeno višje. Dotaknite se, če želite poslati povratne informacije."</string>
<string name="notification_feedback_indicator_demoted" msgid="8880309924296450875">"To obvestilo je bilo uvrščeno nižje. Dotaknite se, če želite poslati povratne informacije."</string>
- <!-- no translation found for nas_upgrade_notification_title (8436359459300146555) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_content (5157550369837103337) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_enable_action (3046406808378726874) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_disable_action (3794833210043497982) -->
- <skip />
+ <string name="nas_upgrade_notification_title" msgid="8436359459300146555">"Pametna obvestila"</string>
+ <string name="nas_upgrade_notification_content" msgid="5157550369837103337">"Predlagana dejanja in odgovore zdaj zagotavljajo pametna obvestila. Prilagodljiva obvestila Android niso več podprta."</string>
+ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"V redu"</string>
+ <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"Izklopi"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"Več o tem"</string>
- <!-- no translation found for nas_upgrade_notification_learn_more_content (2353549817159426430) -->
- <skip />
+ <string name="nas_upgrade_notification_learn_more_content" msgid="2353549817159426430">"Pametna obvestila so v Androidu 12 zamenjala prilagodljiva obvestila Android. Ta funkcija prikazuje predlagana dejanja in odgovore ter organizira vaša obvestila.\n\nPametna obvestila lahko preberejo vso vsebino obvestil, vključno z osebnimi podatki, kot so imena in sporočila stikov. Ta funkcija lahko tudi opusti obvestila ali se odziva nanja (npr. sprejema telefonske klice in upravlja način »Ne moti«)."</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Rutinsko informativno obvestilo o načinu delovanja"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Baterija se bo morda izpraznila, preden jo običajno priključite na polnjenje"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Vklopilo se je varčevanje z energijo baterije za podaljšanje časa delovanja baterije"</string>
@@ -2360,4 +2355,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Podoba blagovne znamke aplikacije"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Preverite nastavitve dostopa"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"Storitev <xliff:g id="SERVICE_NAME">%s</xliff:g> si lahko ogleda in upravlja vaš zaslon. Dotaknite se za pregled."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 3f0b8f3..c12383c 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -1820,8 +1820,7 @@
<string name="mediasize_japanese_kahu" msgid="7290232592648122042">"Kahu"</string>
<string name="mediasize_japanese_kaku2" msgid="7477551750461028312">"Kaku2"</string>
<string name="mediasize_japanese_you4" msgid="5552111912684384833">"You4"</string>
- <!-- no translation found for mediasize_japanese_l (1326765321473431817) -->
- <skip />
+ <string name="mediasize_japanese_l" msgid="1326765321473431817">"L"</string>
<string name="mediasize_unknown_portrait" msgid="3817016220446495613">"Vertikalisht i panjohur"</string>
<string name="mediasize_unknown_landscape" msgid="1584741567225095325">"Orientim i panjohur horizontal"</string>
<string name="write_fail_reason_cancelled" msgid="2344081488493969190">"Anuluar"</string>
@@ -1865,10 +1864,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Përditësuar nga administratori"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Fshirë nga administratori"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"Në rregull"</string>
- <!-- no translation found for battery_saver_description_with_learn_more (750683025714899363) -->
- <skip />
- <!-- no translation found for battery_saver_description (5693741424234005958) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="750683025714899363">"\"Kursyesi i baterisë\" aktivizon \"Temën e errët\" dhe kufizon ose çaktivizon aktivitetin në sfond, disa efekte vizuale dhe veçori të caktuara.\n\n"<annotation id="url">"Mëso më shumë"</annotation></string>
+ <string name="battery_saver_description" msgid="5693741424234005958">"\"Kursyesi i baterisë\" aktivizon \"Temën e errët\" dhe kufizon ose çaktivizon aktivitetin në sfond, disa efekte vizuale dhe veçori të caktuara."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Për të ndihmuar në reduktimin e përdorimit të të dhënave, \"Kursyesi i të dhënave\" pengon që disa aplikacione të dërgojnë apo të marrin të dhëna në sfond. Një aplikacion që po përdor aktualisht mund të ketë qasje te të dhënat, por këtë mund ta bëjë më rrallë. Kjo mund të nënkuptojë, për shembull, se imazhet nuk shfaqen kur troket mbi to."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Të aktivizohet \"Kursyesi i të dhënave\"?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"Aktivizo"</string>
@@ -2088,17 +2085,12 @@
<string name="notification_feedback_indicator_silenced" msgid="3799442124723177262">"Ky njoftim është ulur në nivel si në heshtje. Trokit për të dhënë komente."</string>
<string name="notification_feedback_indicator_promoted" msgid="9030204303764698640">"Ky njoftim është renditur më lart. Trokit për të dhënë komente."</string>
<string name="notification_feedback_indicator_demoted" msgid="8880309924296450875">"Ky njoftim është renditur më poshtë. Trokit për të dhënë komente."</string>
- <!-- no translation found for nas_upgrade_notification_title (8436359459300146555) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_content (5157550369837103337) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_enable_action (3046406808378726874) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_disable_action (3794833210043497982) -->
- <skip />
+ <string name="nas_upgrade_notification_title" msgid="8436359459300146555">"Njoftimet e përmirësuara"</string>
+ <string name="nas_upgrade_notification_content" msgid="5157550369837103337">"Veprimet dhe përgjigjet e sugjeruara tani ofrohen nga njoftimet e përmirësuara. \"Njoftimet me përshtatje të Android\" nuk mbështeten më."</string>
+ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"Në rregull"</string>
+ <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"Çaktivizo"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"Mëso më shumë"</string>
- <!-- no translation found for nas_upgrade_notification_learn_more_content (2353549817159426430) -->
- <skip />
+ <string name="nas_upgrade_notification_learn_more_content" msgid="2353549817159426430">"Njoftimet e përmirësuara kanë zëvendësuar \"Njoftimet me përshtatje të Android\" në Android 12. Kjo veçori shfaq veprimet dhe përgjigjet e sugjeruara dhe organizon njoftimet e tua.\n\nNjoftimet e përmirësuara mund të kenë qasje te përmbajtja e njoftimeve, duke përfshirë informacionet personale si emrat e kontakteve dhe mesazhet. Kjo veçori mund t\'i heqë ose të përgjigjet po ashtu për njoftimet, si p.sh. t\'u përgjigjet telefonatave ose të kontrollojë modalitetin \"Mos shqetëso\"."</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Njoftimi i informacionit të \"Modalitetit rutinë\""</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Bateria mund të mbarojë përpara ngarkimit të zakonshëm"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"\"Kursyesi i baterisë\" u aktivizua për të rritur kohëzgjatjen e baterisë"</string>
@@ -2295,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Imazhi i vendosjes së aplikacionit të markës"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Kontrollo cilësimet e qasjes"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> mund ta shikojë dhe kontrollojë ekranin tënd. Trokit për ta rishikuar."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index e4cadb7..5764878 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -2321,4 +2321,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Имиџ бренда апликације"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Проверите подешавања приступа"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> може да прегледа и контролише екран. Додирните да бисте прегледали."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index e07cf41..ad511fb 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -93,7 +93,7 @@
<string name="notification_channel_mobile_data_status" msgid="1941911162076442474">"Status för mobildata"</string>
<string name="notification_channel_sms" msgid="1243384981025535724">"Sms"</string>
<string name="notification_channel_voice_mail" msgid="8457433203106654172">"Röstmeddelanden"</string>
- <string name="notification_channel_wfc" msgid="9048240466765169038">"Wi-Fi-samtal"</string>
+ <string name="notification_channel_wfc" msgid="9048240466765169038">"wifi-samtal"</string>
<string name="notification_channel_sim" msgid="5098802350325677490">"Status för SIM-kort"</string>
<string name="notification_channel_sim_high_prio" msgid="642361929452850928">"SIM-aviseringar med hög prioritet"</string>
<string name="peerTtyModeFull" msgid="337553730440832160">"Peer-enheten begärde texttelefonläget FULL"</string>
@@ -122,30 +122,30 @@
<string name="roamingText11" msgid="5245687407203281407">"Roamingbanner på"</string>
<string name="roamingText12" msgid="673537506362152640">"Roamingbanner av"</string>
<string name="roamingTextSearching" msgid="5323235489657753486">"Söker efter tjänst"</string>
- <string name="wfcRegErrorTitle" msgid="3193072971584858020">"Det gick inte att konfigurera Wi-Fi-samtal"</string>
+ <string name="wfcRegErrorTitle" msgid="3193072971584858020">"Det gick inte att konfigurera wifi-samtal"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="468830943567116703">"Om du vill ringa samtal och skicka meddelanden via Wi-Fi ber du först operatören att konfigurera tjänsten. Därefter kan du aktivera Wi-Fi-samtal på nytt från Inställningar. (Felkod: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
+ <item msgid="468830943567116703">"Om du vill ringa samtal och skicka meddelanden via wifi ber du först operatören att konfigurera tjänsten. Därefter kan du aktivera wifi-samtal på nytt från Inställningar. (Felkod: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
- <item msgid="4795145070505729156">"Följande fel uppstod när Wi-Fi-samtal skulle registreras hos operatören: <xliff:g id="CODE">%1$s</xliff:g>"</item>
+ <item msgid="4795145070505729156">"Följande fel uppstod när wifi-samtal skulle registreras hos operatören: <xliff:g id="CODE">%1$s</xliff:g>"</item>
</string-array>
<!-- no translation found for wfcSpnFormat_spn (2982505428519096311) -->
<skip />
- <string name="wfcSpnFormat_spn_wifi_calling" msgid="3165949348000906194">"Wi-Fi-samtal via <xliff:g id="SPN">%s</xliff:g>"</string>
- <string name="wfcSpnFormat_spn_wifi_calling_vo_hyphen" msgid="3836827895369365298">"Wi-Fi-samtal med <xliff:g id="SPN">%s</xliff:g>"</string>
+ <string name="wfcSpnFormat_spn_wifi_calling" msgid="3165949348000906194">"wifi-samtal via <xliff:g id="SPN">%s</xliff:g>"</string>
+ <string name="wfcSpnFormat_spn_wifi_calling_vo_hyphen" msgid="3836827895369365298">"wifi-samtal med <xliff:g id="SPN">%s</xliff:g>"</string>
<string name="wfcSpnFormat_wlan_call" msgid="4895315549916165700">"WLAN-samtal"</string>
<string name="wfcSpnFormat_spn_wlan_call" msgid="255919245825481510">"WLAN-samtal via <xliff:g id="SPN">%s</xliff:g>"</string>
- <string name="wfcSpnFormat_spn_wifi" msgid="7232899594327126970">"Wi-Fi via <xliff:g id="SPN">%s</xliff:g>"</string>
- <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="8383917598312067365">"Wi-Fi-samtal | <xliff:g id="SPN">%s</xliff:g>"</string>
+ <string name="wfcSpnFormat_spn_wifi" msgid="7232899594327126970">"wifi via <xliff:g id="SPN">%s</xliff:g>"</string>
+ <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="8383917598312067365">"wifi-samtal | <xliff:g id="SPN">%s</xliff:g>"</string>
<string name="wfcSpnFormat_spn_vowifi" msgid="6865214948822061486">"VoWifi via <xliff:g id="SPN">%s</xliff:g>"</string>
- <string name="wfcSpnFormat_wifi_calling" msgid="6178935388378661755">"Wi-Fi-samtal"</string>
- <string name="wfcSpnFormat_wifi" msgid="1376356951297043426">"Wi-Fi"</string>
- <string name="wfcSpnFormat_wifi_calling_wo_hyphen" msgid="7178561009225028264">"Wi-Fi-samtal"</string>
+ <string name="wfcSpnFormat_wifi_calling" msgid="6178935388378661755">"wifi-samtal"</string>
+ <string name="wfcSpnFormat_wifi" msgid="1376356951297043426">"Wifi"</string>
+ <string name="wfcSpnFormat_wifi_calling_wo_hyphen" msgid="7178561009225028264">"wifi-samtal"</string>
<string name="wfcSpnFormat_vowifi" msgid="8371335230890725606">"VoWifi"</string>
<string name="wifi_calling_off_summary" msgid="5626710010766902560">"Av"</string>
- <string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Ring via Wi-Fi"</string>
+ <string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Ring via wifi"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Ring via mobilnätverk"</string>
- <string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Endast Wi-Fi"</string>
+ <string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Endast wifi"</string>
<!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
<skip />
<string name="crossSimFormat_spn_cross_sim_calling" msgid="5620807020002879057">"<xliff:g id="SPN">%s</xliff:g> används som reserv för samtal"</string>
@@ -512,14 +512,14 @@
<string name="permdesc_changeNetworkState" msgid="649341947816898736">"Tillåter att appen ändrar statusen för en nätverksanslutning."</string>
<string name="permlab_changeTetherState" msgid="9079611809931863861">"ändra sammanlänkad anslutning"</string>
<string name="permdesc_changeTetherState" msgid="3025129606422533085">"Tillåter att appen ändrar statusen för en delad nätverksanslutning."</string>
- <string name="permlab_accessWifiState" msgid="5552488500317911052">"visa Wi-Fi-anslutningar"</string>
- <string name="permdesc_accessWifiState" msgid="6913641669259483363">"Tillåter att appen kommer åt information om Wi-Fi-nätverk, till exempel om Wi-Fi är aktiverat och namn på anslutna Wi-Fi-enheter."</string>
- <string name="permlab_changeWifiState" msgid="7947824109713181554">"anslut och koppla från Wi-Fi"</string>
- <string name="permdesc_changeWifiState" msgid="7170350070554505384">"Tillåter att appen ansluter till och kopplar från Wi-Fi-åtkomstpunkter samt gör ändringar i enhetens konfiguration för Wi-Fi-nätverk."</string>
- <string name="permlab_changeWifiMulticastState" msgid="285626875870754696">"tillåt Wi-Fi multicast-mottagning"</string>
- <string name="permdesc_changeWifiMulticastState" product="tablet" msgid="191079868596433554">"Tillåter att appen tar emot paket som skickats med multicast-adress till alla enheter i ett Wi-Fi-nätverk och inte bara till den här surfplattan. Detta drar mer batteri än när multicastläget inte används."</string>
- <string name="permdesc_changeWifiMulticastState" product="tv" msgid="1336952358450652595">"Tillåter att appen tar emot paket som skickats med multicast-adress till alla enheter i ett Wi-Fi-nätverk och inte bara till den här Android TV-enheten. Detta drar mer batteri än när multicastläget inte används."</string>
- <string name="permdesc_changeWifiMulticastState" product="default" msgid="8296627590220222740">"Tillåter att appen tar emot paket som skickats med multicast-adress till alla enheter i ett Wi-Fi-nätverk och inte bara till den här mobilen. Detta drar mer batteri än när multicastläget inte används."</string>
+ <string name="permlab_accessWifiState" msgid="5552488500317911052">"visa wifi-anslutningar"</string>
+ <string name="permdesc_accessWifiState" msgid="6913641669259483363">"Tillåter att appen kommer åt information om wifi-nätverk, till exempel om wifi är aktiverat och namn på anslutna wifi-enheter."</string>
+ <string name="permlab_changeWifiState" msgid="7947824109713181554">"anslut och koppla från wifi"</string>
+ <string name="permdesc_changeWifiState" msgid="7170350070554505384">"Tillåter att appen ansluter till och kopplar från wifi-åtkomstpunkter samt gör ändringar i enhetens konfiguration för wifi-nätverk."</string>
+ <string name="permlab_changeWifiMulticastState" msgid="285626875870754696">"tillåt wifi multicast-mottagning"</string>
+ <string name="permdesc_changeWifiMulticastState" product="tablet" msgid="191079868596433554">"Tillåter att appen tar emot paket som skickats med multicast-adress till alla enheter i ett wifi-nätverk och inte bara till den här surfplattan. Detta drar mer batteri än när multicastläget inte används."</string>
+ <string name="permdesc_changeWifiMulticastState" product="tv" msgid="1336952358450652595">"Tillåter att appen tar emot paket som skickats med multicast-adress till alla enheter i ett wifi-nätverk och inte bara till den här Android TV-enheten. Detta drar mer batteri än när multicastläget inte används."</string>
+ <string name="permdesc_changeWifiMulticastState" product="default" msgid="8296627590220222740">"Tillåter att appen tar emot paket som skickats med multicast-adress till alla enheter i ett wifi-nätverk och inte bara till den här mobilen. Detta drar mer batteri än när multicastläget inte används."</string>
<string name="permlab_bluetoothAdmin" msgid="6490373569441946064">"få åtkomst till Bluetooth-inställningar"</string>
<string name="permdesc_bluetoothAdmin" product="tablet" msgid="5370837055438574863">"Tillåter att appen konfigurerar den lokala Bluetooth-surfplattan samt upptäcker och parkopplar den med fjärranslutna enheter."</string>
<string name="permdesc_bluetoothAdmin" product="tv" msgid="1623992984547014588">"Tillåter att appen konfigurerar Bluetooth på Android TV-enheten samt upptäcker fjärrenheter och parkopplar enheten med dem."</string>
@@ -1295,7 +1295,7 @@
<string name="ringtone_picker_title_alarm" msgid="7438934548339024767">"Ljud för alarm"</string>
<string name="ringtone_picker_title_notification" msgid="6387191794719608122">"Aviseringsljud"</string>
<string name="ringtone_unknown" msgid="5059495249862816475">"Okänt"</string>
- <string name="wifi_available_sign_in" msgid="381054692557675237">"Logga in på ett Wi-Fi-nätverk"</string>
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Logga in på ett wifi-nätverk"</string>
<string name="network_available_sign_in" msgid="1520342291829283114">"Logga in på nätverket"</string>
<!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
<skip />
@@ -1311,7 +1311,7 @@
<string name="network_switch_metered_toast" msgid="501662047275723743">"Byte av nätverk från <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> till <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
<string-array name="network_switch_type_name">
<item msgid="2255670471736226365">"mobildata"</item>
- <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="5520925862115353992">"Wifi"</item>
<item msgid="1055487873974272842">"Bluetooth"</item>
<item msgid="1616528372438698248">"Ethernet"</item>
<item msgid="9177085807664964627">"VPN"</item>
@@ -1576,10 +1576,10 @@
<string name="data_usage_warning_title" msgid="9034893717078325845">"Datavarning"</string>
<string name="data_usage_warning_body" msgid="1669325367188029454">"Du har använt <xliff:g id="APP">%s</xliff:g> data"</string>
<string name="data_usage_mobile_limit_title" msgid="3911447354393775241">"Gränsen för mobildata har nåtts"</string>
- <string name="data_usage_wifi_limit_title" msgid="2069698056520812232">"Datagränsen för Wi-Fi har uppnåtts"</string>
+ <string name="data_usage_wifi_limit_title" msgid="2069698056520812232">"Datagränsen för wifi har uppnåtts"</string>
<string name="data_usage_limit_body" msgid="3567699582000085710">"Data är pausade under resten av cykeln"</string>
<string name="data_usage_mobile_limit_snoozed_title" msgid="101888478915677895">"Över gränsen för mobildata"</string>
- <string name="data_usage_wifi_limit_snoozed_title" msgid="1622359254521960508">"Över gränsen för Wi-Fi-data"</string>
+ <string name="data_usage_wifi_limit_snoozed_title" msgid="1622359254521960508">"Över gränsen för wifi-data"</string>
<string name="data_usage_limit_snoozed_body" msgid="545146591766765678">"Du överskridit den inställda gränsen med <xliff:g id="SIZE">%s</xliff:g>"</string>
<string name="data_usage_restricted_title" msgid="126711424380051268">"Bakgrundsdata är begränsade"</string>
<string name="data_usage_restricted_body" msgid="5338694433686077733">"Ta bort begränsning."</string>
@@ -2287,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Appens varumärkesbild"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Kontrollera åtkomstinställningar"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> kan visa och styra din skärm. Tryck för att granska."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index c2e14bb..04e2ff3 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -2085,17 +2085,12 @@
<string name="notification_feedback_indicator_silenced" msgid="3799442124723177262">"Arifa hii ilishushwa hadhi kuwa Kimya. Gusa ili utoe maoni."</string>
<string name="notification_feedback_indicator_promoted" msgid="9030204303764698640">"Arifa hii imeorodheshwa katika nafasi ya juu. Gusa ili utoe maoni."</string>
<string name="notification_feedback_indicator_demoted" msgid="8880309924296450875">"Arifa hii imeorodheshwa katika nafasi ya chini. Gusa ili utoe maoni."</string>
- <!-- no translation found for nas_upgrade_notification_title (8436359459300146555) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_content (5157550369837103337) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_enable_action (3046406808378726874) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_disable_action (3794833210043497982) -->
- <skip />
+ <string name="nas_upgrade_notification_title" msgid="8436359459300146555">"Arifa zilizoboreshwa"</string>
+ <string name="nas_upgrade_notification_content" msgid="5157550369837103337">"Majibu na vitendo vinavyopendekezwa sasa vinatolewa na arifa zilizoboreshwa. Arifa Zinazojirekebisha za Android hazitumiki tena."</string>
+ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"Sawa"</string>
+ <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"Zima"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"Pata maelezo zaidi"</string>
- <!-- no translation found for nas_upgrade_notification_learn_more_content (2353549817159426430) -->
- <skip />
+ <string name="nas_upgrade_notification_learn_more_content" msgid="2353549817159426430">"Kipengele cha Arifa Zilizoboreshwa kilichukua nafasi ya Arifa Zinazojirekebisha za Android katika Android 12. Kipengele hiki kinaonyesha majibu na vitendo vinavyopendekezwa na kupanga arifa zako.\n\nKipengele cha Arifa zilizoboreshwa kinaweza kufikia maudhui ya arifa, ikiwa ni pamoja na taarifa binafsi kama vile majina ya anwani na ujumbe. Kipengele hiki kinaweza pia kuondoa au kujibu arifa, kama vile kujibu simu na kudhibiti kipengele cha Usinisumbue."</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Arifa ya maelezo ya Hali ya Kawaida"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Huenda betri itakwisha chaji mapema"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Imewasha Kiokoa Betri ili kurefusha muda wa matumizi ya betri"</string>
@@ -2292,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Picha ya kuweka chapa kwenye programu"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Angalia mipangilio ya kufikia"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> inaweza kuangalia na kudhibiti skrini yako. Gusa ili ukague."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index 23cab42..6e3e189 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -2085,17 +2085,12 @@
<string name="notification_feedback_indicator_silenced" msgid="3799442124723177262">"இந்த அறிவிப்பின் முக்கியத்துவம் நிசப்த நிலைக்குக் குறைத்து அமைக்கப்பட்டது. கருத்து தெரிவிக்க தட்டவும்."</string>
<string name="notification_feedback_indicator_promoted" msgid="9030204303764698640">"இந்த அறிவிப்பின் முக்கியத்துவம் உயர்த்தப்பட்டது. கருத்து தெரிவிக்க தட்டவும்."</string>
<string name="notification_feedback_indicator_demoted" msgid="8880309924296450875">"இந்த அறிவிப்பின் முக்கியத்துவம் குறைக்கப்பட்டது. கருத்து தெரிவிக்க தட்டவும்."</string>
- <!-- no translation found for nas_upgrade_notification_title (8436359459300146555) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_content (5157550369837103337) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_enable_action (3046406808378726874) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_disable_action (3794833210043497982) -->
- <skip />
+ <string name="nas_upgrade_notification_title" msgid="8436359459300146555">"மேம்பட்ட அறிவிப்புகள்"</string>
+ <string name="nas_upgrade_notification_content" msgid="5157550369837103337">"பரிந்துரைக்கப்படும் செயல்களையும் பதில்களையும் இப்போது \'மேம்பட்ட அறிவிப்புகள்\' வழங்குகிறது. Android சூழலுக்கேற்ற அறிவிப்புகள் இனி ஆதரிக்கப்படாது."</string>
+ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"சரி"</string>
+ <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"ஆஃப் செய்"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"மேலும் அறிக"</string>
- <!-- no translation found for nas_upgrade_notification_learn_more_content (2353549817159426430) -->
- <skip />
+ <string name="nas_upgrade_notification_learn_more_content" msgid="2353549817159426430">"Android 12 பதிப்பில் Android அடாப்டிவ் அறிவிப்புகள் இப்போது \'மேம்பட்ட அறிவிப்புகளாக\' மாற்றப்பட்டுள்ளது. இந்த அம்சம், பரிந்துரைக்கப்படும் செயல்களையும் பதில்களையும் காட்டும். மேலும் உங்கள் அறிவிப்புகளை ஒருங்கிணைக்கும்.\n\nமேம்பட்ட அறிவிப்புகளால் அனைத்து அறிவிப்புகளின் உள்ளடக்கத்தையும் (தொடர்புகளின் பெயர்கள், மெசேஜ்கள் போன்ற தனிப்பட்ட தகவல்கள் உட்பட) அணுக முடியும். இந்த அம்சத்தால் அறிவிப்புகளை நிராகரிக்கவும் அவற்றுக்குப் பதிலளிக்கவும்கூட (அழைப்புகளுக்குப் பதிலளிப்பது, தொந்தரவு செய்ய வேண்டாம் அம்சத்தைக் கட்டுப்படுத்துவது போன்றவை) முடியும்."</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"வழக்கமான பேட்டரி சேமிப்பானுக்கான விவர அறிவிப்பு"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"வழக்கமாகச் சார்ஜ் செய்வதற்கு முன்பே பேட்டரி தீர்ந்துபோகக்கூடும்"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"பேட்டரி நிலையை நீட்டிக்க பேட்டரி சேமிப்பான் இயக்கப்பட்டுள்ளது"</string>
@@ -2292,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"ஆப்ஸ் பிராண்டிங் இமேஜ்"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"அணுகல் அமைப்புகளைச் சரிபாருங்கள்"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> சேவையால் உங்கள் திரையைப் பார்க்கவும் கட்டுப்படுத்தவும் முடியும். பார்க்கத் தட்டவும்."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index aa97fb5..9f5c24d 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -1820,8 +1820,7 @@
<string name="mediasize_japanese_kahu" msgid="7290232592648122042">"కాహు"</string>
<string name="mediasize_japanese_kaku2" msgid="7477551750461028312">"కాకు2"</string>
<string name="mediasize_japanese_you4" msgid="5552111912684384833">"యు4"</string>
- <!-- no translation found for mediasize_japanese_l (1326765321473431817) -->
- <skip />
+ <string name="mediasize_japanese_l" msgid="1326765321473431817">"L"</string>
<string name="mediasize_unknown_portrait" msgid="3817016220446495613">"తెలియని పొర్ట్రెయిట్"</string>
<string name="mediasize_unknown_landscape" msgid="1584741567225095325">"తెలియని ల్యాండ్స్కేప్"</string>
<string name="write_fail_reason_cancelled" msgid="2344081488493969190">"రద్దు చేయబడింది"</string>
@@ -1865,10 +1864,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 (750683025714899363) -->
- <skip />
- <!-- no translation found for battery_saver_description (5693741424234005958) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="750683025714899363">"బ్యాటరీ సేవర్ ముదురు రంగు రూపాన్ని ఆన్ చేసి, బ్యాక్గ్రౌండ్ యాక్టివిటీ, కొన్ని విజువల్ ఎఫెక్ట్లు, నిర్దిష్ట ఫీచర్లను పరిమితం చేస్తుంది లేదా ఆఫ్ చేస్తుంది.\n\n"<annotation id="url">"మరింత తెలుసుకోండి"</annotation></string>
+ <string name="battery_saver_description" msgid="5693741424234005958">"బ్యాటరీ సేవర్ ముదురు రంగు రూపాన్ని ఆన్ చేసి, బ్యాక్గ్రౌండ్ యాక్టివిటీ, కొన్ని విజువల్ ఎఫెక్ట్లు, నిర్దిష్ట ఫీచర్లను పరిమితం చేస్తుంది లేదా ఆఫ్ చేస్తుంది."</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>
@@ -2295,4 +2292,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"యాప్ బ్రాండింగ్ ఇమేజ్"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"యాక్సెస్ సెట్టింగ్లను చెక్ చేయండి"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> మీ స్క్రీన్ను చూడవచ్చు, కంట్రోల్ చేయవచ్చు. రివ్యూ చేయడానికి ట్యాప్ చేయండి."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 65a38db..3f338e6 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -2085,17 +2085,12 @@
<string name="notification_feedback_indicator_silenced" msgid="3799442124723177262">"การแจ้งเตือนนี้มีการลดระดับเป็นแบบปิดเสียง แตะเพื่อแสดงความคิดเห็น"</string>
<string name="notification_feedback_indicator_promoted" msgid="9030204303764698640">"การแจ้งเตือนนี้มีการเพิ่มระดับ แตะเพื่อแสดงความคิดเห็น"</string>
<string name="notification_feedback_indicator_demoted" msgid="8880309924296450875">"การแจ้งเตือนนี้มีการลดระดับ แตะเพื่อแสดงความคิดเห็น"</string>
- <!-- no translation found for nas_upgrade_notification_title (8436359459300146555) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_content (5157550369837103337) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_enable_action (3046406808378726874) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_disable_action (3794833210043497982) -->
- <skip />
+ <string name="nas_upgrade_notification_title" msgid="8436359459300146555">"การแจ้งเตือนที่เพิ่มประสิทธิภาพ"</string>
+ <string name="nas_upgrade_notification_content" msgid="5157550369837103337">"การดำเนินการและการตอบกลับที่แนะนำจะแสดงผ่านการแจ้งเตือนที่เพิ่มประสิทธิภาพ ไม่รองรับการแจ้งเตือนแบบปรับอัตโนมัติใน Android อีกต่อไป"</string>
+ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"ตกลง"</string>
+ <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"ปิด"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"ดูข้อมูลเพิ่มเติม"</string>
- <!-- no translation found for nas_upgrade_notification_learn_more_content (2353549817159426430) -->
- <skip />
+ <string name="nas_upgrade_notification_learn_more_content" msgid="2353549817159426430">"การแจ้งเตือนที่เพิ่มประสิทธิภาพมาแทนที่การแจ้งเตือนแบบปรับอัตโนมัติของ Android ใน Android 12 ฟีเจอร์นี้จะแสดงการดำเนินการและการตอบกลับที่แนะนำ ตลอดจนจัดระเบียบการแจ้งเตือน\n\nการแจ้งเตือนที่เพิ่มประสิทธิภาพจะเข้าถึงเนื้อหาของการแจ้งเตือนได้ ซึ่งรวมถึงข้อมูลส่วนบุคคล เช่น ชื่อผู้ติดต่อและข้อความ ฟีเจอร์นี้ยังปิดหรือตอบสนองต่อการแจ้งเตือนได้ด้วย เช่น การรับสายโทรศัพท์และการควบคุมโหมดห้ามรบกวน"</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"การแจ้งเตือนข้อมูลโหมดกิจวัตร"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"แบตเตอรี่อาจหมดก่อนการชาร์จปกติ"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"เปิดใช้งานโหมดประหยัดแบตเตอรี่แล้วเพื่อยืดอายุการใช้งานแบตเตอรี่"</string>
@@ -2292,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"ภาพลักษณ์ของแบรนด์แอปพลิเคชัน"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"ตรวจสอบการตั้งค่าการเข้าถึง"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> จะดูและควบคุมหน้าจอของคุณได้ แตะเพื่อตรวจสอบ"</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index c646cba..3e3289b 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -2287,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Representasyon ng brand ng application"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Tingnan ang mga setting ng pag-access"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"Makikita at makokontrol ng <xliff:g id="SERVICE_NAME">%s</xliff:g> ang iyong screen. I-tap para suriin."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 668ae77..3f1fb4a 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -2287,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Uygulama marka imajı"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Erişim ayarlarını kontrol edin"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g>, ekranınızı görüntüleyip kontrol edebilir. İncelemek için dokunun."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 1eea6317f..b479ec8 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -2151,17 +2151,12 @@
<string name="notification_feedback_indicator_silenced" msgid="3799442124723177262">"Важливість цього сповіщення знижено до рівня \"Без звуку\". Натисніть, щоб надіслати відгук."</string>
<string name="notification_feedback_indicator_promoted" msgid="9030204303764698640">"Важливість цього сповіщення підвищено. Натисніть, щоб надіслати відгук."</string>
<string name="notification_feedback_indicator_demoted" msgid="8880309924296450875">"Важливість цього сповіщення знижено. Натисніть, щоб надіслати відгук."</string>
- <!-- no translation found for nas_upgrade_notification_title (8436359459300146555) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_content (5157550369837103337) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_enable_action (3046406808378726874) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_disable_action (3794833210043497982) -->
- <skip />
+ <string name="nas_upgrade_notification_title" msgid="8436359459300146555">"Покращені сповіщення"</string>
+ <string name="nas_upgrade_notification_content" msgid="5157550369837103337">"Тепер пропоновані дії та відповіді можна знайти в покращених сповіщеннях. Адаптивні сповіщення Android більше не підтримуються."</string>
+ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"OK"</string>
+ <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"Вимкнути"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"Докладніше"</string>
- <!-- no translation found for nas_upgrade_notification_learn_more_content (2353549817159426430) -->
- <skip />
+ <string name="nas_upgrade_notification_learn_more_content" msgid="2353549817159426430">"У версії ОС Android 12 адаптивні сповіщення замінено на покращені. Ця функція допомагає впорядковувати сповіщення й показує в них пропоновані дії та відповіді.\n\nПокращені сповіщення надають доступ до вмісту сповіщень, зокрема до особистої інформації, наприклад повідомлень та імен контактів. Ця функція може автоматично відхиляти сповіщення чи реагувати на них, наприклад відповідати на телефонні дзвінки або керувати режимом \"Не турбувати\"."</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Сповіщення про послідовнсть дій"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Акумулятор може розрядитися раніше ніж зазвичай"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Режим енергозбереження активовано для збільшення часу роботи акумулятора"</string>
@@ -2360,4 +2355,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Зображення фірмової символіки додатка"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Перевірте налаштування доступу"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> може переглядати екран вашого пристрою та керувати ним. Натисніть, щоб переглянути."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 1f056fa..48208ac6 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -1820,8 +1820,7 @@
<string name="mediasize_japanese_kahu" msgid="7290232592648122042">"Kahu"</string>
<string name="mediasize_japanese_kaku2" msgid="7477551750461028312">"Kaku2"</string>
<string name="mediasize_japanese_you4" msgid="5552111912684384833">"You4"</string>
- <!-- no translation found for mediasize_japanese_l (1326765321473431817) -->
- <skip />
+ <string name="mediasize_japanese_l" msgid="1326765321473431817">"L"</string>
<string name="mediasize_unknown_portrait" msgid="3817016220446495613">"نامعلوم پورٹریٹ"</string>
<string name="mediasize_unknown_landscape" msgid="1584741567225095325">"نامعلوم لینڈ اسکیپ"</string>
<string name="write_fail_reason_cancelled" msgid="2344081488493969190">"منسوخ کر دیا گیا"</string>
@@ -1865,10 +1864,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 (750683025714899363) -->
- <skip />
- <!-- no translation found for battery_saver_description (5693741424234005958) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="750683025714899363">"بیٹری سیور گہری تھیم کو آن کرتی ہے اور پس منظر کی سرگرمی، کچھ بصری اثرات اور کچھ مخصوص خصوصیات کو محدود یا آف کرتی ہے۔\n\n"<annotation id="url">"مزید جانیں"</annotation></string>
+ <string name="battery_saver_description" msgid="5693741424234005958">"بیٹری سیور گہری تھیم کو آن کرتی ہے اور پس منظر کی سرگرمی، کچھ بصری اثرات اور کچھ مخصوص خصوصیات کو محدود یا آف کرتی ہے۔"</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>
@@ -2088,17 +2085,12 @@
<string name="notification_feedback_indicator_silenced" msgid="3799442124723177262">"اس اطلاع کو خاموش پر ڈیموٹ کیا گيا۔ تاثرات فراہم کرنے کے ليے تھپتھپائیں۔"</string>
<string name="notification_feedback_indicator_promoted" msgid="9030204303764698640">"اس اطلاع کو اعلی درجہ دیا گیا۔ تاثرات فراہم کرنے کے ليے تھپتھپائیں۔"</string>
<string name="notification_feedback_indicator_demoted" msgid="8880309924296450875">"اس اطلاع کو کم درجہ دیا گیا۔ تاثرات فراہم کرنے کے ليے تھپتھپائیں۔"</string>
- <!-- no translation found for nas_upgrade_notification_title (8436359459300146555) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_content (5157550369837103337) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_enable_action (3046406808378726874) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_disable_action (3794833210043497982) -->
- <skip />
+ <string name="nas_upgrade_notification_title" msgid="8436359459300146555">"بہتر کردہ اطلاعات"</string>
+ <string name="nas_upgrade_notification_content" msgid="5157550369837103337">"تجویز کردہ کارروائیاں اور جوابات اب بہتر اطلاعات کے ذریعے فراہم کیے جاتے ہیں۔ Android اڈاپٹیو کی اطلاعات اب تعاون یافتہ نہیں ہیں۔"</string>
+ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"ٹھیک ہے"</string>
+ <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"آف کریں"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"مزید جانیں"</string>
- <!-- no translation found for nas_upgrade_notification_learn_more_content (2353549817159426430) -->
- <skip />
+ <string name="nas_upgrade_notification_learn_more_content" msgid="2353549817159426430">"Android 12 میں بہتر کردہ اطلاعات کو Android اڈاپٹیو کی اطلاعات سے تبدیل کیا گیا ہے۔ یہ خصوصیت تجویز کردہ کارروائیاں اور جوابات دکھاتی ہے اور آپ کی اطلاعات کا نظم کرتی ہے۔\n\nبہتر کردہ اطلاعات رابطوں کے نام اور پیغامات جیسی ذاتی معلومات سمیت اطلاعات کے مواد تک رسائی حاصل کر سکتی ہیں۔ یہ خصوصیت اطلاعات کو برخاست کر سکتی ہے یا اس کا جواب بھی دے سکتی ہے جیسے فون کالز کا جواب دینا اور ڈسٹرب نہ کریں کو کنٹرول کرنا۔"</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"روٹین موڈ معلومات کی اطلاع"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"معمول چارج سے پہلے بیٹری ختم ہو سکتی ہے"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"بیٹری لائف کو بڑھانے کے لیے بیٹری سیور کو فعال کر دیا گیا ہے"</string>
@@ -2295,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"ایپلیکیشن کی برانڈنگ تصویر"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"رسائی کی ترتیبات چیک کریں"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> آپ کی اسکرین کو دیکھ اور کنٹرول کر سکتی ہیں۔ جائزے کے لیے تھپتھپائیں۔"</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index bac2b6f..4c69030 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -1820,8 +1820,7 @@
<string name="mediasize_japanese_kahu" msgid="7290232592648122042">"Kahu"</string>
<string name="mediasize_japanese_kaku2" msgid="7477551750461028312">"Kaku2"</string>
<string name="mediasize_japanese_you4" msgid="5552111912684384833">"You4"</string>
- <!-- no translation found for mediasize_japanese_l (1326765321473431817) -->
- <skip />
+ <string name="mediasize_japanese_l" msgid="1326765321473431817">"L"</string>
<string name="mediasize_unknown_portrait" msgid="3817016220446495613">"Noma’lum bo‘yiga"</string>
<string name="mediasize_unknown_landscape" msgid="1584741567225095325">"Noma’lum eniga"</string>
<string name="write_fail_reason_cancelled" msgid="2344081488493969190">"Bekor qilindi"</string>
@@ -1865,10 +1864,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>
- <!-- no translation found for battery_saver_description_with_learn_more (750683025714899363) -->
- <skip />
- <!-- no translation found for battery_saver_description (5693741424234005958) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="750683025714899363">"Quvvat tejash tungi mavzuni yoqadi va orqa fondagi harakatlar, ayrim vizual effektlar va ayrim funksiyalarni cheklaydi yoki oʻchiradi.\n\n"<annotation id="url">"Batafsil"</annotation></string>
+ <string name="battery_saver_description" msgid="5693741424234005958">"Quvvat tejash tungi mavzuni yoqadi va orqa fondagi harakatlar, ayrim vizual effektlar va ayrim funksiyalarni cheklaydi yoki oʻchiradi."</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>
@@ -2290,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Ilova brendining rasmi"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Ruxsat sozlamalarini tekshiring"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> ekraningizni koʻrishi va boshqarishi mumkin. Tekshirish uchun bosing."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index c65229c..74b3846 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -2085,17 +2085,12 @@
<string name="notification_feedback_indicator_silenced" msgid="3799442124723177262">"Hệ thống đã hạ mức ưu tiên của thông báo này xuống thành Im lặng. Hãy nhấn để chia sẻ ý kiến phản hồi."</string>
<string name="notification_feedback_indicator_promoted" msgid="9030204303764698640">"Hệ thống đã nâng mức ưu tiên của thông báo này. Hãy nhấn để chia sẻ ý kiến phản hồi."</string>
<string name="notification_feedback_indicator_demoted" msgid="8880309924296450875">"Hệ thống đã hạ mức ưu tiên của thông báo này. Hãy nhấn để chia sẻ ý kiến phản hồi."</string>
- <!-- no translation found for nas_upgrade_notification_title (8436359459300146555) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_content (5157550369837103337) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_enable_action (3046406808378726874) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_disable_action (3794833210043497982) -->
- <skip />
+ <string name="nas_upgrade_notification_title" msgid="8436359459300146555">"Thông báo nâng cao"</string>
+ <string name="nas_upgrade_notification_content" msgid="5157550369837103337">"Thông báo nâng cao hiện cung cấp các thao tác và câu trả lời đề xuất. Thông báo thích ứng trên Android không được hỗ trợ nữa."</string>
+ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"OK"</string>
+ <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"Tắt"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"Tìm hiểu thêm"</string>
- <!-- no translation found for nas_upgrade_notification_learn_more_content (2353549817159426430) -->
- <skip />
+ <string name="nas_upgrade_notification_learn_more_content" msgid="2353549817159426430">"Thông báo nâng cao đã thay thế Thông báo thích ứng trên Android trong Android 12. Tính năng này hiển thị những thao tác và câu trả lời đề xuất, đồng thời sắp xếp các thông báo của bạn.\n\nThông báo nâng cao có thể đọc mọi nội dung thông báo, bao gồm cả thông tin cá nhân như tên liên hệ và tin nhắn. Tính năng này cũng có thể đóng hoặc phản hồi các thông báo, chẳng hạn như trả lời cuộc gọi điện thoại và điều khiển chế độ Không làm phiền."</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Thông báo cung cấp thông tin về chế độ sạc thông thường"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Pin có thể hết trước khi sạc bình thường"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Trình tiết kiệm pin được kích hoạt để kéo dài thời lượng pin"</string>
@@ -2292,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Hình ảnh thương hiệu của ứng dụng"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Hãy kiểm tra chế độ cài đặt quyền truy cập"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> có thể xem và điều khiển màn hình của bạn. Nhấn để xem lại."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index df13cc0..3122053 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -1820,8 +1820,7 @@
<string name="mediasize_japanese_kahu" msgid="7290232592648122042">"Kahu"</string>
<string name="mediasize_japanese_kaku2" msgid="7477551750461028312">"Kaku2"</string>
<string name="mediasize_japanese_you4" msgid="5552111912684384833">"You4"</string>
- <!-- no translation found for mediasize_japanese_l (1326765321473431817) -->
- <skip />
+ <string name="mediasize_japanese_l" msgid="1326765321473431817">"大"</string>
<string name="mediasize_unknown_portrait" msgid="3817016220446495613">"未知(纵向)"</string>
<string name="mediasize_unknown_landscape" msgid="1584741567225095325">"未知(横向)"</string>
<string name="write_fail_reason_cancelled" msgid="2344081488493969190">"已取消"</string>
@@ -1865,10 +1864,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 (750683025714899363) -->
- <skip />
- <!-- no translation found for battery_saver_description (5693741424234005958) -->
- <skip />
+ <string name="battery_saver_description_with_learn_more" msgid="750683025714899363">"在省电模式下,系统会启用深色主题,并限制或关闭后台活动、部分视觉效果和某些功能。\n\n"<annotation id="url">"了解详情"</annotation></string>
+ <string name="battery_saver_description" msgid="5693741424234005958">"在省电模式下,系统会启用深色主题,并限制或关闭后台活动、部分视觉效果和某些功能。"</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>
@@ -2088,17 +2085,12 @@
<string name="notification_feedback_indicator_silenced" msgid="3799442124723177262">"系统已将此通知的重要性降低为“静音”。点按即可提供反馈。"</string>
<string name="notification_feedback_indicator_promoted" msgid="9030204303764698640">"系统已提升此通知的重要性。点按即可提供反馈。"</string>
<string name="notification_feedback_indicator_demoted" msgid="8880309924296450875">"系统已降低此通知的重要性。点按即可提供反馈。"</string>
- <!-- no translation found for nas_upgrade_notification_title (8436359459300146555) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_content (5157550369837103337) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_enable_action (3046406808378726874) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_disable_action (3794833210043497982) -->
- <skip />
+ <string name="nas_upgrade_notification_title" msgid="8436359459300146555">"增强型通知功能"</string>
+ <string name="nas_upgrade_notification_content" msgid="5157550369837103337">"建议的操作和回复目前由增强型通知功能提供。系统不再支持 Android 自适应通知功能。"</string>
+ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"确定"</string>
+ <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"关闭"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"了解详情"</string>
- <!-- no translation found for nas_upgrade_notification_learn_more_content (2353549817159426430) -->
- <skip />
+ <string name="nas_upgrade_notification_learn_more_content" msgid="2353549817159426430">"在 Android 12 中,增强型通知功能取代了 Android 自适应通知功能。增强型通知功能可以显示建议的操作和回复,并可将通知整理得井井有条。\n\n增强型通知功能可以访问通知内容,包括联系人名称和消息等个人信息。该功能还可以关闭或响应通知,例如接听来电以及控制勿扰模式。"</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"日常安排模式信息通知"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"电池电量可能会在您平时的充电时间之前耗尽"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"已启用省电模式以延长电池续航时间"</string>
@@ -2295,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"应用品牌图片"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"查看权限设置"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g>可以查看和控制您的屏幕。点按即可查看。"</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 3addf92..1597477 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -2085,17 +2085,12 @@
<string name="notification_feedback_indicator_silenced" msgid="3799442124723177262">"此通知的重要性已降低為「靜音」。輕按即可提供意見。"</string>
<string name="notification_feedback_indicator_promoted" msgid="9030204303764698640">"此通知的重要性已提升。輕按即可提供意見。"</string>
<string name="notification_feedback_indicator_demoted" msgid="8880309924296450875">"此通知的重要性已降級。輕按即可提供意見。"</string>
- <!-- no translation found for nas_upgrade_notification_title (8436359459300146555) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_content (5157550369837103337) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_enable_action (3046406808378726874) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_disable_action (3794833210043497982) -->
- <skip />
+ <string name="nas_upgrade_notification_title" msgid="8436359459300146555">"強化通知"</string>
+ <string name="nas_upgrade_notification_content" msgid="5157550369837103337">"建議的操作和回覆目前由強化通知功能提供。系統已不再支援 Android 自動調整通知功能。"</string>
+ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"確定"</string>
+ <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"關閉"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"瞭解詳情"</string>
- <!-- no translation found for nas_upgrade_notification_learn_more_content (2353549817159426430) -->
- <skip />
+ <string name="nas_upgrade_notification_learn_more_content" msgid="2353549817159426430">"在 Android 12 中,我們將 Android 自動調整通知取代成強化通知。此功能可顯示建議操作和回覆,以及整理通知。\n\n強化通知功能可讀取所有通知內容 (包括聯絡人姓名和訊息等個人資料),以及關閉或回應通知,例如接聽來電和控制「請勿騷擾」功能。"</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"「日常安排模式」資料通知"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"電量可能會在日常充電前耗盡"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"「省電模式」已啟用,以便延長電池壽命"</string>
@@ -2292,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"應用程式品牌形象"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"檢查存取權設定"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"<xliff:g id="SERVICE_NAME">%s</xliff:g> 可以查看及控制您的螢幕。輕按即可查看。"</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 08071be..7d02173 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -2085,17 +2085,12 @@
<string name="notification_feedback_indicator_silenced" msgid="3799442124723177262">"這則通知的重要性已降低為「靜音」。輕觸即可提供意見。"</string>
<string name="notification_feedback_indicator_promoted" msgid="9030204303764698640">"這則通知的重要性順序已調高。輕觸即可提供意見。"</string>
<string name="notification_feedback_indicator_demoted" msgid="8880309924296450875">"這則通知的重要性順序已調降。輕觸即可提供意見。"</string>
- <!-- no translation found for nas_upgrade_notification_title (8436359459300146555) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_content (5157550369837103337) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_enable_action (3046406808378726874) -->
- <skip />
- <!-- no translation found for nas_upgrade_notification_disable_action (3794833210043497982) -->
- <skip />
+ <string name="nas_upgrade_notification_title" msgid="8436359459300146555">"加強型通知"</string>
+ <string name="nas_upgrade_notification_content" msgid="5157550369837103337">"建議的操作和回覆內容目前是由加強型通知功能提供。系統已不再支援 Android 自動調整通知功能。"</string>
+ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"確定"</string>
+ <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"關閉"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"瞭解詳情"</string>
- <!-- no translation found for nas_upgrade_notification_learn_more_content (2353549817159426430) -->
- <skip />
+ <string name="nas_upgrade_notification_learn_more_content" msgid="2353549817159426430">"在 Android 12 中,加強型通知功能已取代 Android 自動調整通知。這項功能可以顯示建議的操作和回覆內容,也可以整理通知。\n\n加強型通知功能可存取通知內容,包括聯絡人名稱和訊息內文等個人資訊。此外,這項功能還能關閉或回覆通知,例如接聽來電及控管「零打擾」功能。"</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"日常安排模式資訊通知"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"電池電力可能會在你平常的充電時間前耗盡"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"已啟用省電模式以延長電池續航力"</string>
@@ -2292,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"應用程式品牌圖片"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"查看存取權設定"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"「<xliff:g id="SERVICE_NAME">%s</xliff:g>」可以查看及控管你的螢幕。輕觸即可查看。"</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 07a597b..f68a7aa 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -2287,4 +2287,8 @@
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Isithombe sokubhrenda i-application"</string>
<string name="view_and_control_notification_title" msgid="4300765399209912240">"Hlola amasethingi wokufinyelela"</string>
<string name="view_and_control_notification_content" msgid="8003766498562604034">"I-<xliff:g id="SERVICE_NAME">%s</xliff:g> ingakwazi ukubuka nokulawula isikrini sakho. Thepha ukuze ubuyekeze."</string>
+ <!-- no translation found for ui_translation_accessibility_translated_text (3197547218178944544) -->
+ <skip />
+ <!-- no translation found for ui_translation_accessibility_translation_finished (3057830947610088465) -->
+ <skip />
</resources>
diff --git a/core/res/res/values/locale_config.xml b/core/res/res/values/locale_config.xml
index 3c65caf..e9b42d3 100644
--- a/core/res/res/values/locale_config.xml
+++ b/core/res/res/values/locale_config.xml
@@ -74,7 +74,7 @@
<item>ar-TD-u-nu-latn</item> <!-- Arabic (Chad, Western Digits) -->
<item>ar-TN</item> <!-- Arabic (Tunisia) -->
<item>ar-TN-u-nu-arab</item> <!-- Arabic (Tunisia, Arabic-Indic Digits) -->
- <item>ar-XB</item> <!-- Right-to-left pseudolocale -->
+ <item>ar-XB</item> <!-- Arabic (Pseudo-Bidi) -->
<item>ar-YE</item> <!-- Arabic (Yemen) -->
<item>ar-YE-u-nu-latn</item> <!-- Arabic (Yemen, Western Digits) -->
<item>as-IN</item> <!-- Assamese (India) -->
@@ -104,6 +104,7 @@
<item>ca-FR</item> <!-- Catalan (France) -->
<item>ca-IT</item> <!-- Catalan (Italy) -->
<item>ce-RU</item> <!-- Chechen (Russia) -->
+ <item>ceb-PH</item> <!-- Cebuano (Philippines) -->
<item>cgg-UG</item> <!-- Chiga (Uganda) -->
<item>chr-US</item> <!-- Cherokee (United States) -->
<item>cs-CZ</item> <!-- Czech (Czechia) -->
@@ -119,15 +120,18 @@
<item>de-LI</item> <!-- German (Liechtenstein) -->
<item>de-LU</item> <!-- German (Luxembourg) -->
<item>dje-NE</item> <!-- Zarma (Niger) -->
+ <item>doi-IN</item> <!-- Dogri (India) -->
<item>dsb-DE</item> <!-- Lower Sorbian (Germany) -->
<item>dua-CM</item> <!-- Duala (Cameroon) -->
<item>dyo-SN</item> <!-- Jola-Fonyi (Senegal) -->
<item>dz-BT</item> <!-- Dzongkha (Bhutan) -->
+ <item>dz-BT-u-nu-latn</item> <!-- Dzongkha (Bhutan, Western Digits) -->
<item>ebu-KE</item> <!-- Embu (Kenya) -->
<item>ee-GH</item> <!-- Ewe (Ghana) -->
<item>ee-TG</item> <!-- Ewe (Togo) -->
<item>el-CY</item> <!-- Greek (Cyprus) -->
<item>el-GR</item> <!-- Greek (Greece) -->
+ <item>en-AE</item> <!-- English (United Arab Emirates) -->
<item>en-AG</item> <!-- English (Antigua & Barbuda) -->
<item>en-AI</item> <!-- English (Anguilla) -->
<item>en-AS</item> <!-- English (American Samoa) -->
@@ -181,7 +185,7 @@
<item>en-LS</item> <!-- English (Lesotho) -->
<item>en-MG</item> <!-- English (Madagascar) -->
<item>en-MH</item> <!-- English (Marshall Islands) -->
- <item>en-MO</item> <!-- English (Macau) -->
+ <item>en-MO</item> <!-- English (Macao) -->
<item>en-MP</item> <!-- English (Northern Mariana Islands) -->
<item>en-MS</item> <!-- English (Montserrat) -->
<item>en-MT</item> <!-- English (Malta) -->
@@ -212,7 +216,7 @@
<item>en-SL</item> <!-- English (Sierra Leone) -->
<item>en-SS</item> <!-- English (South Sudan) -->
<item>en-SX</item> <!-- English (Sint Maarten) -->
- <item>en-SZ</item> <!-- English (Swaziland) -->
+ <item>en-SZ</item> <!-- English (Eswatini) -->
<item>en-TC</item> <!-- English (Turks & Caicos Islands) -->
<item>en-TK</item> <!-- English (Tokelau) -->
<item>en-TO</item> <!-- English (Tonga) -->
@@ -227,7 +231,7 @@
<item>en-VI</item> <!-- English (U.S. Virgin Islands) -->
<item>en-VU</item> <!-- English (Vanuatu) -->
<item>en-WS</item> <!-- English (Samoa) -->
- <item>en-XA</item> <!-- Left-to-right pseudolocale -->
+ <item>en-XA</item> <!-- English (Pseudo-Accents) -->
<item>en-ZA</item> <!-- English (South Africa) -->
<item>en-ZM</item> <!-- English (Zambia) -->
<item>en-ZW</item> <!-- English (Zimbabwe) -->
@@ -265,10 +269,42 @@
<item>fa-AF-u-nu-latn</item> <!-- Persian (Afghanistan, Western Digits) -->
<item>fa-IR</item> <!-- Persian (Iran) -->
<item>fa-IR-u-nu-latn</item> <!-- Persian (Iran, Western Digits) -->
- <item>ff-CM</item> <!-- Fulah (Cameroon) -->
- <item>ff-GN</item> <!-- Fulah (Guinea) -->
- <item>ff-MR</item> <!-- Fulah (Mauritania) -->
- <item>ff-SN</item> <!-- Fulah (Senegal) -->
+ <item>ff-Adlm-BF</item> <!-- Fulah (Adlam, Burkina Faso) -->
+ <item>ff-Adlm-BF-u-nu-latn</item> <!-- Fulah (Adlam, Burkina Faso, Western Digits) -->
+ <item>ff-Adlm-CM</item> <!-- Fulah (Adlam, Cameroon) -->
+ <item>ff-Adlm-CM-u-nu-latn</item> <!-- Fulah (Adlam, Cameroon, Western Digits) -->
+ <item>ff-Adlm-GH</item> <!-- Fulah (Adlam, Ghana) -->
+ <item>ff-Adlm-GH-u-nu-latn</item> <!-- Fulah (Adlam, Ghana, Western Digits) -->
+ <item>ff-Adlm-GM</item> <!-- Fulah (Adlam, Gambia) -->
+ <item>ff-Adlm-GM-u-nu-latn</item> <!-- Fulah (Adlam, Gambia, Western Digits) -->
+ <item>ff-Adlm-GN</item> <!-- Fulah (Adlam, Guinea) -->
+ <item>ff-Adlm-GN-u-nu-latn</item> <!-- Fulah (Adlam, Guinea, Western Digits) -->
+ <item>ff-Adlm-GW</item> <!-- Fulah (Adlam, Guinea-Bissau) -->
+ <item>ff-Adlm-GW-u-nu-latn</item> <!-- Fulah (Adlam, Guinea-Bissau, Western Digits) -->
+ <item>ff-Adlm-LR</item> <!-- Fulah (Adlam, Liberia) -->
+ <item>ff-Adlm-LR-u-nu-latn</item> <!-- Fulah (Adlam, Liberia, Western Digits) -->
+ <item>ff-Adlm-MR</item> <!-- Fulah (Adlam, Mauritania) -->
+ <item>ff-Adlm-MR-u-nu-latn</item> <!-- Fulah (Adlam, Mauritania, Western Digits) -->
+ <item>ff-Adlm-NE</item> <!-- Fulah (Adlam, Niger) -->
+ <item>ff-Adlm-NE-u-nu-latn</item> <!-- Fulah (Adlam, Niger, Western Digits) -->
+ <item>ff-Adlm-NG</item> <!-- Fulah (Adlam, Nigeria) -->
+ <item>ff-Adlm-NG-u-nu-latn</item> <!-- Fulah (Adlam, Nigeria, Western Digits) -->
+ <item>ff-Adlm-SL</item> <!-- Fulah (Adlam, Sierra Leone) -->
+ <item>ff-Adlm-SL-u-nu-latn</item> <!-- Fulah (Adlam, Sierra Leone, Western Digits) -->
+ <item>ff-Adlm-SN</item> <!-- Fulah (Adlam, Senegal) -->
+ <item>ff-Adlm-SN-u-nu-latn</item> <!-- Fulah (Adlam, Senegal, Western Digits) -->
+ <item>ff-Latn-BF</item> <!-- Fulah (Latin, Burkina Faso) -->
+ <item>ff-Latn-CM</item> <!-- Fulah (Latin, Cameroon) -->
+ <item>ff-Latn-GH</item> <!-- Fulah (Latin, Ghana) -->
+ <item>ff-Latn-GM</item> <!-- Fulah (Latin, Gambia) -->
+ <item>ff-Latn-GN</item> <!-- Fulah (Latin, Guinea) -->
+ <item>ff-Latn-GW</item> <!-- Fulah (Latin, Guinea-Bissau) -->
+ <item>ff-Latn-LR</item> <!-- Fulah (Latin, Liberia) -->
+ <item>ff-Latn-MR</item> <!-- Fulah (Latin, Mauritania) -->
+ <item>ff-Latn-NE</item> <!-- Fulah (Latin, Niger) -->
+ <item>ff-Latn-NG</item> <!-- Fulah (Latin, Nigeria) -->
+ <item>ff-Latn-SL</item> <!-- Fulah (Latin, Sierra Leone) -->
+ <item>ff-Latn-SN</item> <!-- Fulah (Latin, Senegal) -->
<item>fi-FI</item> <!-- Finnish (Finland) -->
<item>fil-PH</item> <!-- Filipino (Philippines) -->
<item>fo-DK</item> <!-- Faroese (Denmark) -->
@@ -321,6 +357,7 @@
<item>fr-YT</item> <!-- French (Mayotte) -->
<item>fur-IT</item> <!-- Friulian (Italy) -->
<item>fy-NL</item> <!-- Western Frisian (Netherlands) -->
+ <item>ga-GB</item> <!-- Irish (United Kingdom) -->
<item>ga-IE</item> <!-- Irish (Ireland) -->
<item>gd-GB</item> <!-- Scottish Gaelic (United Kingdom) -->
<item>gl-ES</item> <!-- Galician (Spain) -->
@@ -340,6 +377,7 @@
<item>hsb-DE</item> <!-- Upper Sorbian (Germany) -->
<item>hu-HU</item> <!-- Hungarian (Hungary) -->
<item>hy-AM</item> <!-- Armenian (Armenia) -->
+ <item>ia-001</item> <!-- Interlingua (World) -->
<item>ig-NG</item> <!-- Igbo (Nigeria) -->
<item>ii-CN</item> <!-- Sichuan Yi (China) -->
<item>in-ID</item> <!-- Indonesian (Indonesia) -->
@@ -347,10 +385,12 @@
<item>it-CH</item> <!-- Italian (Switzerland) -->
<item>it-IT</item> <!-- Italian (Italy) -->
<item>it-SM</item> <!-- Italian (San Marino) -->
+ <item>it-VA</item> <!-- Italian (Vatican City) -->
<item>iw-IL</item> <!-- Hebrew (Israel) -->
<item>ja-JP</item> <!-- Japanese (Japan) -->
<item>jgo-CM</item> <!-- Ngomba (Cameroon) -->
<item>jmc-TZ</item> <!-- Machame (Tanzania) -->
+ <item>jv-ID</item> <!-- Javanese (Indonesia) -->
<item>ka-GE</item> <!-- Georgian (Georgia) -->
<item>kab-DZ</item> <!-- Kabyle (Algeria) -->
<item>kam-KE</item> <!-- Kamba (Kenya) -->
@@ -386,6 +426,7 @@
<item>luo-KE</item> <!-- Luo (Kenya) -->
<item>luy-KE</item> <!-- Luyia (Kenya) -->
<item>lv-LV</item> <!-- Latvian (Latvia) -->
+ <item>mai-IN</item> <!-- Maithili (India) -->
<item>mas-KE</item> <!-- Masai (Kenya) -->
<item>mas-TZ</item> <!-- Masai (Tanzania) -->
<item>mer-KE</item> <!-- Meru (Kenya) -->
@@ -393,23 +434,31 @@
<item>mg-MG</item> <!-- Malagasy (Madagascar) -->
<item>mgh-MZ</item> <!-- Makhuwa-Meetto (Mozambique) -->
<item>mgo-CM</item> <!-- Metaʼ (Cameroon) -->
- <item>mk-MK</item> <!-- Macedonian (Macedonia (FYROM)) -->
+ <item>mi-NZ</item> <!-- Maori (New Zealand) -->
+ <item>mk-MK</item> <!-- Macedonian (North Macedonia) -->
<item>ml-IN</item> <!-- Malayalam (India) -->
<item>mn-MN</item> <!-- Mongolian (Mongolia) -->
+ <item>mni-IN</item> <!-- Manipuri (India) -->
+ <item>mni-IN-u-nu-latn</item> <!-- Manipuri (India, Western Digits) -->
<item>mr-IN</item> <!-- Marathi (India) -->
+ <item>mr-IN-u-nu-latn</item> <!-- Marathi (India, Western Digits) -->
<item>ms-BN</item> <!-- Malay (Brunei) -->
+ <item>ms-ID</item> <!-- Malay (Indonesia) -->
<item>ms-MY</item> <!-- Malay (Malaysia) -->
<item>ms-SG</item> <!-- Malay (Singapore) -->
<item>mt-MT</item> <!-- Maltese (Malta) -->
<item>my-MM</item> <!-- Burmese (Myanmar (Burma)) -->
<item>my-MM-u-nu-latn</item> <!-- Burmese (Myanmar (Burma), Western Digits) -->
<item>mzn-IR</item> <!-- Mazanderani (Iran) -->
+ <item>mzn-IR-u-nu-latn</item> <!-- Mazanderani (Iran, Western Digits) -->
<item>naq-NA</item> <!-- Nama (Namibia) -->
<item>nb-NO</item> <!-- Norwegian Bokmål (Norway) -->
<item>nb-SJ</item> <!-- Norwegian Bokmål (Svalbard & Jan Mayen) -->
<item>nd-ZW</item> <!-- North Ndebele (Zimbabwe) -->
<item>ne-IN</item> <!-- Nepali (India) -->
+ <item>ne-IN-u-nu-latn</item> <!-- Nepali (India, Western Digits) -->
<item>ne-NP</item> <!-- Nepali (Nepal) -->
+ <item>ne-NP-u-nu-latn</item> <!-- Nepali (Nepal, Western Digits) -->
<item>nl-AW</item> <!-- Dutch (Aruba) -->
<item>nl-BE</item> <!-- Dutch (Belgium) -->
<item>nl-BQ</item> <!-- Dutch (Caribbean Netherlands) -->
@@ -427,14 +476,22 @@
<item>os-GE</item> <!-- Ossetic (Georgia) -->
<item>os-RU</item> <!-- Ossetic (Russia) -->
<item>pa-Arab-PK</item> <!-- Punjabi (Arabic, Pakistan) -->
+ <item>pa-Arab-PK-u-nu-latn</item> <!-- Punjabi (Arabic, Pakistan, Western Digits) -->
<item>pa-Guru-IN</item> <!-- Punjabi (Gurmukhi, India) -->
+ <item>pcm-NG</item> <!-- Nigerian Pidgin (Nigeria) -->
<item>pl-PL</item> <!-- Polish (Poland) -->
<item>ps-AF</item> <!-- Pashto (Afghanistan) -->
+ <item>ps-AF-u-nu-latn</item> <!-- Pashto (Afghanistan, Western Digits) -->
+ <item>ps-PK</item> <!-- Pashto (Pakistan) -->
+ <item>ps-PK-u-nu-latn</item> <!-- Pashto (Pakistan, Western Digits) -->
<item>pt-AO</item> <!-- Portuguese (Angola) -->
<item>pt-BR</item> <!-- Portuguese (Brazil) -->
+ <item>pt-CH</item> <!-- Portuguese (Switzerland) -->
<item>pt-CV</item> <!-- Portuguese (Cape Verde) -->
+ <item>pt-GQ</item> <!-- Portuguese (Equatorial Guinea) -->
<item>pt-GW</item> <!-- Portuguese (Guinea-Bissau) -->
- <item>pt-MO</item> <!-- Portuguese (Macau) -->
+ <item>pt-LU</item> <!-- Portuguese (Luxembourg) -->
+ <item>pt-MO</item> <!-- Portuguese (Macao) -->
<item>pt-MZ</item> <!-- Portuguese (Mozambique) -->
<item>pt-PT</item> <!-- Portuguese (Portugal) -->
<item>pt-ST</item> <!-- Portuguese (São Tomé & Príncipe) -->
@@ -455,9 +512,15 @@
<item>ru-UA</item> <!-- Russian (Ukraine) -->
<item>rw-RW</item> <!-- Kinyarwanda (Rwanda) -->
<item>rwk-TZ</item> <!-- Rwa (Tanzania) -->
+ <item>sa-IN</item> <!-- Sanskrit (India) -->
<item>sah-RU</item> <!-- Sakha (Russia) -->
<item>saq-KE</item> <!-- Samburu (Kenya) -->
+ <item>sat-IN</item> <!-- Santali (India) -->
+ <item>sat-IN-u-nu-latn</item> <!-- Santali (India, Western Digits) -->
<item>sbp-TZ</item> <!-- Sangu (Tanzania) -->
+ <item>sd-Arab-PK</item> <!-- Sindhi (Arabic, Pakistan) -->
+ <item>sd-Arab-PK-u-nu-latn</item> <!-- Sindhi (Arabic, Pakistan, Western Digits) -->
+ <item>sd-Deva-IN</item> <!-- Sindhi (Devanagari, India) -->
<item>se-FI</item> <!-- Northern Sami (Finland) -->
<item>se-NO</item> <!-- Northern Sami (Norway) -->
<item>se-SE</item> <!-- Northern Sami (Sweden) -->
@@ -474,7 +537,7 @@
<item>so-KE</item> <!-- Somali (Kenya) -->
<item>so-SO</item> <!-- Somali (Somalia) -->
<item>sq-AL</item> <!-- Albanian (Albania) -->
- <item>sq-MK</item> <!-- Albanian (Macedonia (FYROM)) -->
+ <item>sq-MK</item> <!-- Albanian (North Macedonia) -->
<item>sq-XK</item> <!-- Albanian (Kosovo) -->
<item>sr-Cyrl-BA</item> <!-- Serbian (Cyrillic, Bosnia & Herzegovina) -->
<item>sr-Cyrl-ME</item> <!-- Serbian (Cyrillic, Montenegro) -->
@@ -484,6 +547,7 @@
<item>sr-Latn-ME</item> <!-- Serbian (Latin, Montenegro) -->
<item>sr-Latn-RS</item> <!-- Serbian (Latin, Serbia) -->
<item>sr-Latn-XK</item> <!-- Serbian (Latin, Kosovo) -->
+ <item>su-ID</item> <!-- Sundanese (Indonesia) -->
<item>sv-AX</item> <!-- Swedish (Åland Islands) -->
<item>sv-FI</item> <!-- Swedish (Finland) -->
<item>sv-SE</item> <!-- Swedish (Sweden) -->
@@ -498,10 +562,13 @@
<item>te-IN</item> <!-- Telugu (India) -->
<item>teo-KE</item> <!-- Teso (Kenya) -->
<item>teo-UG</item> <!-- Teso (Uganda) -->
+ <item>tg-TJ</item> <!-- Tajik (Tajikistan) -->
<item>th-TH</item> <!-- Thai (Thailand) -->
+ <item>tk-TM</item> <!-- Turkmen (Turkmenistan) -->
<item>to-TO</item> <!-- Tongan (Tonga) -->
<item>tr-CY</item> <!-- Turkish (Cyprus) -->
<item>tr-TR</item> <!-- Turkish (Turkey) -->
+ <item>tt-RU</item> <!-- Tatar (Russia) -->
<item>twq-NE</item> <!-- Tasawaq (Niger) -->
<item>tzm-MA</item> <!-- Central Atlas Tamazight (Morocco) -->
<item>ug-CN</item> <!-- Uyghur (China) -->
@@ -511,11 +578,13 @@
<item>ur-PK</item> <!-- Urdu (Pakistan) -->
<item>ur-PK-u-nu-arabext</item> <!-- Urdu (Pakistan, Extended Arabic-Indic Digits) -->
<item>uz-Arab-AF</item> <!-- Uzbek (Arabic, Afghanistan) -->
+ <item>uz-Arab-AF-u-nu-latn</item> <!-- Uzbek (Arabic, Afghanistan, Western Digits) -->
<item>uz-Cyrl-UZ</item> <!-- Uzbek (Cyrillic, Uzbekistan) -->
<item>uz-Latn-UZ</item> <!-- Uzbek (Latin, Uzbekistan) -->
<item>vi-VN</item> <!-- Vietnamese (Vietnam) -->
<item>vun-TZ</item> <!-- Vunjo (Tanzania) -->
<item>wae-CH</item> <!-- Walser (Switzerland) -->
+ <item>wo-SN</item> <!-- Wolof (Senegal) -->
<item>xog-UG</item> <!-- Soga (Uganda) -->
<item>yav-CM</item> <!-- Yangben (Cameroon) -->
<item>yo-BJ</item> <!-- Yoruba (Benin) -->
@@ -525,10 +594,10 @@
<item>zgh-MA</item> <!-- Standard Moroccan Tamazight (Morocco) -->
<item>zh-Hans-CN</item> <!-- Chinese (Simplified, China) -->
<item>zh-Hans-HK</item> <!-- Chinese (Simplified, Hong Kong) -->
- <item>zh-Hans-MO</item> <!-- Chinese (Simplified, Macau) -->
+ <item>zh-Hans-MO</item> <!-- Chinese (Simplified, Macao) -->
<item>zh-Hans-SG</item> <!-- Chinese (Simplified, Singapore) -->
<item>zh-Hant-HK</item> <!-- Chinese (Traditional, Hong Kong) -->
- <item>zh-Hant-MO</item> <!-- Chinese (Traditional, Macau) -->
+ <item>zh-Hant-MO</item> <!-- Chinese (Traditional, Macao) -->
<item>zh-Hant-TW</item> <!-- Chinese (Traditional, Taiwan) -->
<item>zu-ZA</item> <!-- Zulu (South Africa) -->
</string-array>
diff --git a/core/tests/coretests/Android.bp b/core/tests/coretests/Android.bp
index e1d44dc..415b1f2 100644
--- a/core/tests/coretests/Android.bp
+++ b/core/tests/coretests/Android.bp
@@ -52,7 +52,8 @@
"truth-prebuilt",
"print-test-util-lib",
"testng",
- "servicestests-utils"
+ "servicestests-utils",
+ "AppSearchTestUtils",
],
libs: [
@@ -66,7 +67,7 @@
"framework-res",
],
jni_libs: [
- "libpowermanagertest_jni",
+ "libpowermanagertest_jni",
],
platform_apis: true,
diff --git a/core/tests/coretests/src/android/app/appsearch/AppSearchSessionUnitTest.java b/core/tests/coretests/src/android/app/appsearch/AppSearchSessionUnitTest.java
index 3d18337..d51004c 100644
--- a/core/tests/coretests/src/android/app/appsearch/AppSearchSessionUnitTest.java
+++ b/core/tests/coretests/src/android/app/appsearch/AppSearchSessionUnitTest.java
@@ -25,6 +25,8 @@
import androidx.test.core.app.ApplicationProvider;
+import com.android.server.appsearch.testing.AppSearchEmail;
+
import org.junit.Before;
import org.junit.Test;
diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/AppSearchEmailTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/AppSearchEmailTest.java
index 3989ec7..29b0228 100644
--- a/core/tests/coretests/src/android/app/appsearch/external/app/AppSearchEmailTest.java
+++ b/core/tests/coretests/src/android/app/appsearch/external/app/AppSearchEmailTest.java
@@ -18,6 +18,8 @@
import static com.google.common.truth.Truth.assertThat;
+import com.android.server.appsearch.testing.AppSearchEmail;
+
import org.junit.Test;
public class AppSearchEmailTest {
diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/PutDocumentsRequestTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/PutDocumentsRequestTest.java
index a1f7986..6fad4b8d 100644
--- a/core/tests/coretests/src/android/app/appsearch/external/app/PutDocumentsRequestTest.java
+++ b/core/tests/coretests/src/android/app/appsearch/external/app/PutDocumentsRequestTest.java
@@ -19,6 +19,8 @@
import static com.google.common.truth.Truth.assertThat;
+import com.android.server.appsearch.testing.AppSearchEmail;
+
import com.google.common.collect.ImmutableSet;
import org.junit.Test;
diff --git a/core/tests/coretests/src/android/app/appsearch/external/util/BundleUtilTest.java b/core/tests/coretests/src/android/app/appsearch/external/util/BundleUtilTest.java
index ece37f8..680ce52 100644
--- a/core/tests/coretests/src/android/app/appsearch/external/util/BundleUtilTest.java
+++ b/core/tests/coretests/src/android/app/appsearch/external/util/BundleUtilTest.java
@@ -213,6 +213,17 @@
.isNotEqualTo(BundleUtil.deepHashCode(inputs[1]));
}
+ @Test
+ public void testDeepCopy() {
+ Bundle input = createThoroughBundle();
+ Bundle output = BundleUtil.deepCopy(input);
+ assertThat(input).isNotSameInstanceAs(output);
+ assertThat(BundleUtil.deepEquals(input, output)).isTrue();
+
+ output.getIntegerArrayList("integerArrayList").add(5);
+ assertThat(BundleUtil.deepEquals(input, output)).isFalse();
+ }
+
private static Bundle createThoroughBundle() {
Bundle toy1 = new Bundle();
toy1.putString("a", "a");
diff --git a/core/tests/coretests/src/android/graphics/FontListParserTest.java b/core/tests/coretests/src/android/graphics/FontListParserTest.java
index b2df98d..22f6ec0 100644
--- a/core/tests/coretests/src/android/graphics/FontListParserTest.java
+++ b/core/tests/coretests/src/android/graphics/FontListParserTest.java
@@ -325,6 +325,6 @@
XmlPullParser parser = Xml.newPullParser();
parser.setInput(buffer, "UTF-8");
parser.nextTag();
- return FontListParser.readFamily(parser, "", null);
+ return FontListParser.readFamily(parser, "", null, true);
}
}
diff --git a/core/tests/coretests/src/android/hardware/input/InputDeviceLightsManagerTest.java b/core/tests/coretests/src/android/hardware/input/InputDeviceLightsManagerTest.java
index 412b367..8b39beb 100644
--- a/core/tests/coretests/src/android/hardware/input/InputDeviceLightsManagerTest.java
+++ b/core/tests/coretests/src/android/hardware/input/InputDeviceLightsManagerTest.java
@@ -33,6 +33,7 @@
import android.hardware.lights.Light;
import android.hardware.lights.LightState;
import android.hardware.lights.LightsManager;
+import android.hardware.lights.LightsRequest;
import android.os.IBinder;
import android.platform.test.annotations.Presubmit;
import android.util.ArrayMap;
@@ -224,4 +225,25 @@
session.close();
verify(mIInputManagerMock).closeLightSession(eq(DEVICE_ID), eq(token));
}
+
+ @Test
+ public void testLightsRequest() throws Exception {
+ Light light = new Light(1 /* id */, 0 /* ordinal */, Light.LIGHT_TYPE_INPUT_PLAYER_ID);
+ LightState state = new LightState(0xf1);
+ LightsRequest request = new Builder().addLight(light, state).build();
+
+ // Covers the LightsRequest.getLights
+ assertThat(request.getLights().size()).isEqualTo(1);
+ assertThat(request.getLights().get(0)).isEqualTo(1);
+
+ // Covers the LightsRequest.getLightStates
+ assertThat(request.getLightStates().size()).isEqualTo(1);
+ assertThat(request.getLightStates().get(0)).isEqualTo(state);
+
+ // Covers the LightsRequest.getLightsAndStates
+ assertThat(request.getLightsAndStates().size()).isEqualTo(1);
+ assertThat(request.getLightsAndStates().containsKey(1)).isTrue();
+ assertThat(request.getLightsAndStates().get(1)).isEqualTo(state);
+ }
+
}
diff --git a/data/etc/car/com.android.car.shell.xml b/data/etc/car/com.android.car.shell.xml
index 578c46e..d48d751 100644
--- a/data/etc/car/com.android.car.shell.xml
+++ b/data/etc/car/com.android.car.shell.xml
@@ -25,6 +25,7 @@
<permission name="android.car.permission.CAR_DIAGNOSTICS"/>
<permission name="android.car.permission.CAR_DRIVING_STATE"/>
<permission name="android.car.permission.CAR_POWER"/>
+ <permission name="android.car.permission.CONTROL_CAR_POWER_POLICY"/>
<permission name="android.car.permission.CONTROL_CAR_CLIMATE"/>
<permission name="android.car.permission.CAR_TIRES"/>
<permission name="android.car.permission.READ_CAR_STEERING"/>
diff --git a/graphics/java/android/graphics/FontListParser.java b/graphics/java/android/graphics/FontListParser.java
index 7f5b752..93a336e 100644
--- a/graphics/java/android/graphics/FontListParser.java
+++ b/graphics/java/android/graphics/FontListParser.java
@@ -74,7 +74,7 @@
parser.setInput(in, null);
parser.nextTag();
return readFamilies(parser, "/system/fonts/", new FontCustomizationParser.Result(), null,
- 0, 0);
+ 0, 0, true);
}
/**
@@ -116,7 +116,7 @@
parser.setInput(is, null);
parser.nextTag();
return readFamilies(parser, systemFontDir, oemCustomization, updatableFontMap,
- lastModifiedDate, configVersion);
+ lastModifiedDate, configVersion, false /* filter out the non-exising files */);
}
}
@@ -126,7 +126,8 @@
@NonNull FontCustomizationParser.Result customization,
@Nullable Map<String, File> updatableFontMap,
long lastModifiedDate,
- int configVersion)
+ int configVersion,
+ boolean allowNonExistingFile)
throws XmlPullParserException, IOException {
List<FontConfig.FontFamily> families = new ArrayList<>();
List<FontConfig.Alias> aliases = new ArrayList<>(customization.getAdditionalAliases());
@@ -139,7 +140,11 @@
if (parser.getEventType() != XmlPullParser.START_TAG) continue;
String tag = parser.getName();
if (tag.equals("family")) {
- FontConfig.FontFamily family = readFamily(parser, fontDir, updatableFontMap);
+ FontConfig.FontFamily family = readFamily(parser, fontDir, updatableFontMap,
+ allowNonExistingFile);
+ if (family == null) {
+ continue;
+ }
String name = family.getName();
if (name == null || !oemNamedFamilies.containsKey(name)) {
// The OEM customization overrides system named family. Skip if OEM
@@ -165,9 +170,15 @@
/**
* Read family tag in fonts.xml or oem_customization.xml
+ *
+ * @param parser An XML parser.
+ * @param fontDir a font directory name.
+ * @param updatableFontMap a updated font file map.
+ * @param allowNonExistingFile true to allow font file that doesn't exists
+ * @return a FontFamily instance. null if no font files are available in this FontFamily.
*/
- public static FontConfig.FontFamily readFamily(XmlPullParser parser, String fontDir,
- @Nullable Map<String, File> updatableFontMap)
+ public static @Nullable FontConfig.FontFamily readFamily(XmlPullParser parser, String fontDir,
+ @Nullable Map<String, File> updatableFontMap, boolean allowNonExistingFile)
throws XmlPullParserException, IOException {
final String name = parser.getAttributeValue(null, "name");
final String lang = parser.getAttributeValue("", "lang");
@@ -177,7 +188,11 @@
if (parser.getEventType() != XmlPullParser.START_TAG) continue;
final String tag = parser.getName();
if (tag.equals(TAG_FONT)) {
- fonts.add(readFont(parser, fontDir, updatableFontMap));
+ FontConfig.Font font = readFont(parser, fontDir, updatableFontMap,
+ allowNonExistingFile);
+ if (font != null) {
+ fonts.add(font);
+ }
} else {
skip(parser);
}
@@ -190,6 +205,9 @@
intVariant = FontConfig.FontFamily.VARIANT_ELEGANT;
}
}
+ if (fonts.isEmpty()) {
+ return null;
+ }
return new FontConfig.FontFamily(fonts, name, LocaleList.forLanguageTags(lang), intVariant);
}
@@ -197,10 +215,11 @@
private static final Pattern FILENAME_WHITESPACE_PATTERN =
Pattern.compile("^[ \\n\\r\\t]+|[ \\n\\r\\t]+$");
- private static FontConfig.Font readFont(
+ private static @Nullable FontConfig.Font readFont(
@NonNull XmlPullParser parser,
@NonNull String fontDir,
- @Nullable Map<String, File> updatableFontMap)
+ @Nullable Map<String, File> updatableFontMap,
+ boolean allowNonExistingFile)
throws XmlPullParserException, IOException {
String indexStr = parser.getAttributeValue(null, ATTR_INDEX);
@@ -253,7 +272,9 @@
File file = new File(filePath);
-
+ if (!(allowNonExistingFile || file.isFile())) {
+ return null;
+ }
return new FontConfig.Font(file,
originalPath == null ? null : new File(originalPath),
diff --git a/graphics/java/android/graphics/fonts/FontCustomizationParser.java b/graphics/java/android/graphics/fonts/FontCustomizationParser.java
index 42033ba..9c01a4b 100644
--- a/graphics/java/android/graphics/fonts/FontCustomizationParser.java
+++ b/graphics/java/android/graphics/fonts/FontCustomizationParser.java
@@ -134,7 +134,7 @@
throw new IllegalArgumentException("customizationType must be specified");
}
if (customizationType.equals("new-named-family")) {
- out.add(FontListParser.readFamily(parser, fontDir, updatableFontMap));
+ out.add(FontListParser.readFamily(parser, fontDir, updatableFontMap, false));
} else {
throw new IllegalArgumentException("Unknown customizationType=" + customizationType);
}
diff --git a/libs/WindowManager/Shell/res/layout/bubble_overflow_container.xml b/libs/WindowManager/Shell/res/layout/bubble_overflow_container.xml
index 8224d95..270186a 100644
--- a/libs/WindowManager/Shell/res/layout/bubble_overflow_container.xml
+++ b/libs/WindowManager/Shell/res/layout/bubble_overflow_container.xml
@@ -27,24 +27,26 @@
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/bubble_overflow_recycler"
- android:layout_gravity="center_horizontal"
android:nestedScrollingEnabled="false"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"/>
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_gravity="center_horizontal"
+ android:gravity="center"/>
<LinearLayout
android:id="@+id/bubble_overflow_empty_state"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
+ android:visibility="gone"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
android:paddingLeft="@dimen/bubble_overflow_empty_state_padding"
android:paddingRight="@dimen/bubble_overflow_empty_state_padding"
android:orientation="vertical"
android:gravity="center">
<ImageView
+ android:id="@+id/bubble_overflow_empty_state_image"
android:layout_width="@dimen/bubble_empty_overflow_image_height"
android:layout_height="@dimen/bubble_empty_overflow_image_height"
- android:id="@+id/bubble_overflow_empty_state_image"
android:scaleType="fitCenter"
android:layout_gravity="center"/>
@@ -60,12 +62,12 @@
<TextView
android:id="@+id/bubble_overflow_empty_subtitle"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
android:fontFamily="@*android:string/config_bodyFontFamily"
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Body2"
android:textColor="?android:attr/textColorSecondary"
android:text="@string/bubble_overflow_empty_subtitle"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
android:paddingBottom="@dimen/bubble_empty_overflow_subtitle_padding"
android:gravity="center"/>
</LinearLayout>
diff --git a/libs/WindowManager/Shell/res/layout/bubble_overflow_view.xml b/libs/WindowManager/Shell/res/layout/bubble_overflow_view.xml
index c1f67bd..d07107c 100644
--- a/libs/WindowManager/Shell/res/layout/bubble_overflow_view.xml
+++ b/libs/WindowManager/Shell/res/layout/bubble_overflow_view.xml
@@ -32,12 +32,14 @@
android:id="@+id/bubble_view_name"
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
android:textSize="13sp"
- android:layout_width="fill_parent"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
android:lines="2"
android:ellipsize="end"
android:layout_gravity="center"
android:paddingTop="@dimen/bubble_overflow_text_padding"
+ android:paddingEnd="@dimen/bubble_overflow_text_padding"
+ android:paddingStart="@dimen/bubble_overflow_text_padding"
android:gravity="center"/>
</LinearLayout>
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 fe1ed4b..fe6a8bd 100644
--- a/libs/WindowManager/Shell/res/layout/bubble_stack_user_education.xml
+++ b/libs/WindowManager/Shell/res/layout/bubble_stack_user_education.xml
@@ -38,6 +38,7 @@
android:gravity="start"
android:textAlignment="viewStart"
android:text="@string/bubbles_user_education_title"
+ android:textColor="?android:attr/textColorPrimaryInverse"
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Headline"/>
<TextView
@@ -48,6 +49,7 @@
android:gravity="start"
android:textAlignment="viewStart"
android:text="@string/bubbles_user_education_description"
+ android:textColor="?android:attr/textColorPrimaryInverse"
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 8de06c7..3d48e40 100644
--- a/libs/WindowManager/Shell/res/layout/bubbles_manage_button_education.xml
+++ b/libs/WindowManager/Shell/res/layout/bubbles_manage_button_education.xml
@@ -41,6 +41,7 @@
android:ellipsize="end"
android:gravity="start"
android:textAlignment="viewStart"
+ android:textColor="?android:attr/textColorPrimaryInverse"
android:text="@string/bubbles_user_education_manage_title"
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Headline"/>
@@ -55,6 +56,7 @@
android:ellipsize="end"
android:gravity="start"
android:textAlignment="viewStart"
+ android:textColor="?android:attr/textColorPrimaryInverse"
android:fontFamily="@*android:string/config_bodyFontFamily"
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Body2"/>
diff --git a/libs/WindowManager/Shell/res/values/dimen.xml b/libs/WindowManager/Shell/res/values/dimen.xml
index ef731235..d94030d 100644
--- a/libs/WindowManager/Shell/res/values/dimen.xml
+++ b/libs/WindowManager/Shell/res/values/dimen.xml
@@ -125,7 +125,9 @@
<dimen name="bubble_expanded_view_slop">8dp</dimen>
<!-- Default (and minimum) height of the expanded view shown when the bubble is expanded -->
<dimen name="bubble_expanded_default_height">180dp</dimen>
- <!-- Default height of bubble overflow -->
+ <!-- On large screens the width of the expanded view is restricted to this size. -->
+ <dimen name="bubble_expanded_view_tablet_width">412dp</dimen>
+ <!-- Default (and minimum) height of bubble overflow -->
<dimen name="bubble_overflow_height">480dp</dimen>
<!-- Bubble overflow padding when there are no bubbles -->
<dimen name="bubble_overflow_empty_state_padding">16dp</dimen>
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 abe1f71..696f705 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
@@ -19,6 +19,7 @@
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
import static com.android.wm.shell.bubbles.BubbleDebugConfig.DEBUG_BUBBLE_EXPANDED_VIEW;
@@ -335,7 +336,10 @@
mOverflowView = (BubbleOverflowContainerView) LayoutInflater.from(getContext()).inflate(
R.layout.bubble_overflow_container, null /* root */);
mOverflowView.setBubbleController(mController);
- mExpandedViewContainer.addView(mOverflowView);
+ FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT);
+ mExpandedViewContainer.addView(mOverflowView, lp);
+ mExpandedViewContainer.setLayoutParams(
+ new LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT));
bringChildToFront(mOverflowView);
mSettingsIcon.setVisibility(GONE);
} else {
@@ -600,9 +604,9 @@
return;
}
- if (mBubble != null || mIsOverflow) {
+ if ((mBubble != null && mTaskView != null) || mIsOverflow) {
float desiredHeight = mIsOverflow
- ? mOverflowHeight
+ ? mPositioner.isLargeScreen() ? getMaxExpandedHeight() : mOverflowHeight
: mBubble.getDesiredHeight(mContext);
desiredHeight = Math.max(desiredHeight, mMinHeight);
float height = Math.min(desiredHeight, getMaxExpandedHeight());
@@ -657,10 +661,10 @@
+ getBubbleKey());
}
mExpandedViewContainerLocation = containerLocationOnScreen;
+ updateHeight();
if (mTaskView != null
&& mTaskView.getVisibility() == VISIBLE
&& mTaskView.isAttachedToWindow()) {
- updateHeight();
mTaskView.onLocationChanged();
}
if (mIsOverflow) {
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 f7c7285..af5b3a6 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
@@ -26,7 +26,6 @@
import android.content.res.TypedArray;
import android.graphics.Color;
import android.util.AttributeSet;
-import android.util.DisplayMetrics;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@@ -51,8 +50,6 @@
* Container view for showing aged out bubbles.
*/
public class BubbleOverflowContainerView extends LinearLayout {
- static final String EXTRA_BUBBLE_CONTROLLER = "bubble_controller";
-
private static final String TAG = TAG_WITH_CLASS_NAME ? "BubbleOverflowActivity" : TAG_BUBBLES;
private LinearLayout mEmptyState;
@@ -64,18 +61,16 @@
private RecyclerView mRecyclerView;
private List<Bubble> mOverflowBubbles = new ArrayList<>();
- private class NoScrollGridLayoutManager extends GridLayoutManager {
- NoScrollGridLayoutManager(Context context, int columns) {
+ private class OverflowGridLayoutManager extends GridLayoutManager {
+ OverflowGridLayoutManager(Context context, int columns) {
super(context, columns);
}
- @Override
- public boolean canScrollVertically() {
- if (getResources().getConfiguration().orientation
- == Configuration.ORIENTATION_LANDSCAPE) {
- return super.canScrollVertically();
- }
- return false;
- }
+
+// @Override
+// public boolean canScrollVertically() {
+// // TODO (b/162006693): this should be based on items in the list & available height
+// return true;
+// }
@Override
public int getColumnCountForAccessibility(RecyclerView.Recycler recycler,
@@ -137,47 +132,24 @@
Resources res = getResources();
final int columns = res.getInteger(R.integer.bubbles_overflow_columns);
mRecyclerView.setLayoutManager(
- new NoScrollGridLayoutManager(getContext(), columns));
-
- DisplayMetrics displayMetrics = new DisplayMetrics();
- getContext().getDisplay().getMetrics(displayMetrics);
-
- final int overflowPadding = res.getDimensionPixelSize(R.dimen.bubble_overflow_padding);
- final int recyclerViewWidth = displayMetrics.widthPixels - (overflowPadding * 2);
- final int viewWidth = recyclerViewWidth / columns;
-
- final int maxOverflowBubbles = res.getInteger(R.integer.bubbles_max_overflow);
- final int rows = (int) Math.ceil((double) maxOverflowBubbles / columns);
- final int recyclerViewHeight = res.getDimensionPixelSize(R.dimen.bubble_overflow_height)
- - res.getDimensionPixelSize(R.dimen.bubble_overflow_padding);
- final int viewHeight = recyclerViewHeight / rows;
-
+ new OverflowGridLayoutManager(getContext(), columns));
mAdapter = new BubbleOverflowAdapter(getContext(), mOverflowBubbles,
mController::promoteBubbleFromOverflow,
- mController.getPositioner(),
- viewWidth, viewHeight);
+ mController.getPositioner());
mRecyclerView.setAdapter(mAdapter);
mOverflowBubbles.clear();
mOverflowBubbles.addAll(mController.getOverflowBubbles());
mAdapter.notifyDataSetChanged();
- // Currently BubbleExpandedView.mExpandedViewContainer is WRAP_CONTENT so use the same
- // width we would use for the recycler view
- LayoutParams lp = (LayoutParams) mEmptyState.getLayoutParams();
- lp.width = recyclerViewWidth;
- updateEmptyStateVisibility();
-
mController.setOverflowListener(mDataListener);
+ updateEmptyStateVisibility();
updateTheme();
}
void updateEmptyStateVisibility() {
- if (mOverflowBubbles.isEmpty()) {
- mEmptyState.setVisibility(View.VISIBLE);
- } else {
- mEmptyState.setVisibility(View.GONE);
- }
+ mEmptyState.setVisibility(mOverflowBubbles.isEmpty() ? View.VISIBLE : View.GONE);
+ mRecyclerView.setVisibility(mOverflowBubbles.isEmpty() ? View.GONE : View.VISIBLE);
}
/**
@@ -258,20 +230,15 @@
private Consumer<Bubble> mPromoteBubbleFromOverflow;
private BubblePositioner mPositioner;
private List<Bubble> mBubbles;
- private int mWidth;
- private int mHeight;
BubbleOverflowAdapter(Context context,
List<Bubble> list,
Consumer<Bubble> promoteBubble,
- BubblePositioner positioner,
- int width, int height) {
+ BubblePositioner positioner) {
mContext = context;
mBubbles = list;
mPromoteBubbleFromOverflow = promoteBubble;
mPositioner = positioner;
- mWidth = width;
- mHeight = height;
}
@Override
@@ -284,8 +251,6 @@
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
- params.width = mWidth;
- params.height = mHeight;
overflowView.setLayoutParams(params);
// Ensure name has enough contrast.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java
index a81c2d8..ae1a053 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java
@@ -70,10 +70,16 @@
private int mBubbleSize;
private int mBubbleBitmapSize;
+ private int mExpandedViewLargeScreenWidth;
+ private int mExpandedViewPadding;
+ private int mPointerHeight;
+ private int mBubblePaddingTop;
private PointF mPinLocation;
private PointF mRestingStackPosition;
+ private int[] mLeftRightPadding = new int[2];
+ private boolean mIsLargeScreen;
private boolean mShowingInTaskbar;
private @TaskbarPosition int mTaskbarPosition = TASKBAR_POSITION_NONE;
private int mTaskbarIconSize;
@@ -99,15 +105,17 @@
return;
}
WindowInsets metricInsets = windowMetrics.getWindowInsets();
-
Insets insets = metricInsets.getInsetsIgnoringVisibility(WindowInsets.Type.navigationBars()
| WindowInsets.Type.statusBars()
| WindowInsets.Type.displayCutout());
+ mIsLargeScreen = mContext.getResources().getConfiguration().smallestScreenWidthDp >= 600;
+
if (BubbleDebugConfig.DEBUG_POSITIONER) {
Log.w(TAG, "update positioner:"
- + " rotation= " + mRotation
+ + " rotation: " + mRotation
+ " insets: " + insets
+ + " isLargeScreen: " + mIsLargeScreen
+ " bounds: " + windowMetrics.getBounds()
+ " showingInTaskbar: " + mShowingInTaskbar);
}
@@ -143,6 +151,11 @@
Resources res = mContext.getResources();
mBubbleSize = res.getDimensionPixelSize(R.dimen.individual_bubble_size);
mBubbleBitmapSize = res.getDimensionPixelSize(R.dimen.bubble_bitmap_size);
+ mExpandedViewLargeScreenWidth = res.getDimensionPixelSize(
+ R.dimen.bubble_expanded_view_tablet_width);
+ mExpandedViewPadding = res.getDimensionPixelSize(R.dimen.bubble_expanded_view_padding);
+ mPointerHeight = res.getDimensionPixelSize(R.dimen.bubble_pointer_height);
+ mBubblePaddingTop = res.getDimensionPixelSize(R.dimen.bubble_padding_top);
if (mShowingInTaskbar) {
adjustForTaskbar();
}
@@ -189,13 +202,16 @@
return mInsets;
}
- /**
- * @return whether the device is in landscape orientation.
- */
+ /** @return whether the device is in landscape orientation. */
public boolean isLandscape() {
return mRotation == Surface.ROTATION_90 || mRotation == Surface.ROTATION_270;
}
+ /** @return whether the screen is considered large. */
+ public boolean isLargeScreen() {
+ return mIsLargeScreen;
+ }
+
/**
* Indicates how bubbles appear when expanded.
*
@@ -204,7 +220,7 @@
* to the left or right side.
*/
public boolean showBubblesVertically() {
- return isLandscape() || mShowingInTaskbar;
+ return isLandscape() || mShowingInTaskbar || mIsLargeScreen;
}
/** Size of the bubble account for badge & dot. */
@@ -224,6 +240,45 @@
}
/**
+ * Calculates the left & right padding for the bubble expanded view.
+ *
+ * On larger screens the width of the expanded view is restricted via this padding.
+ * On landscape the bubble overflow expanded view is also restricted via this padding.
+ */
+ public int[] getExpandedViewPadding(boolean onLeft, boolean isOverflow) {
+ int leftPadding = mInsets.left + mExpandedViewPadding;
+ int rightPadding = mInsets.right + mExpandedViewPadding;
+ final boolean isLargeOrOverflow = mIsLargeScreen || isOverflow;
+ if (showBubblesVertically()) {
+ if (!onLeft) {
+ rightPadding += mPointerHeight + mBubbleSize;
+ leftPadding += isLargeOrOverflow
+ ? (mPositionRect.width() - rightPadding - mExpandedViewLargeScreenWidth)
+ : 0;
+ } else {
+ //TODO: pointer height should be padding between pointer & bubbles here & above
+ leftPadding += mPointerHeight + mBubbleSize;
+ rightPadding += isLargeOrOverflow
+ ? (mPositionRect.width() - leftPadding - mExpandedViewLargeScreenWidth)
+ : 0;
+ }
+ }
+ mLeftRightPadding[0] = leftPadding;
+ mLeftRightPadding[1] = rightPadding;
+ return mLeftRightPadding;
+ }
+
+ /** Calculates the y position of the expanded view when it is expanded. */
+ public float getExpandedViewY() {
+ final int top = getAvailableRect().top;
+ if (showBubblesVertically()) {
+ return top + mExpandedViewPadding;
+ } else {
+ return top + mBubbleSize + mBubblePaddingTop;
+ }
+ }
+
+ /**
* Sets the stack's most recent position along the edge of the screen. This is saved when the
* last bubble is removed, so that the stack can be restored in its previous position.
*/
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 0f5d0ef..c4d3387 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
@@ -35,7 +35,6 @@
import android.graphics.Color;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
-import android.graphics.Insets;
import android.graphics.Outline;
import android.graphics.Paint;
import android.graphics.PointF;
@@ -246,7 +245,6 @@
private int mMaxBubbles;
private int mBubbleSize;
private int mBubbleElevation;
- private int mBubblePaddingTop;
private int mBubbleTouchPadding;
private int mExpandedViewPadding;
private int mPointerHeight;
@@ -768,7 +766,6 @@
mMaxBubbles = res.getInteger(R.integer.bubbles_max_rendered);
mBubbleSize = res.getDimensionPixelSize(R.dimen.individual_bubble_size);
mBubbleElevation = res.getDimensionPixelSize(R.dimen.bubble_elevation);
- mBubblePaddingTop = res.getDimensionPixelSize(R.dimen.bubble_padding_top);
mBubbleTouchPadding = res.getDimensionPixelSize(R.dimen.bubble_touch_padding);
mPointerHeight = res.getDimensionPixelSize(R.dimen.bubble_pointer_height);
mImeOffset = res.getDimensionPixelSize(R.dimen.pip_ime_offset);
@@ -905,7 +902,7 @@
afterExpandedViewAnimation();
} /* after */);
mExpandedViewContainer.setTranslationX(0f);
- mExpandedViewContainer.setTranslationY(getExpandedViewY());
+ mExpandedViewContainer.setTranslationY(mPositioner.getExpandedViewY());
mExpandedViewContainer.setAlpha(1f);
}
removeOnLayoutChangeListener(mOrientationChangedListener);
@@ -1247,9 +1244,6 @@
/** Respond to the display size change by recalculating view size and location. */
public void onDisplaySizeChanged() {
updateOverflow();
-
- Resources res = getContext().getResources();
- mBubblePaddingTop = res.getDimensionPixelSize(R.dimen.bubble_padding_top);
mBubbleSize = mPositioner.getBubbleSize();
for (Bubble b : mBubbleData.getBubbles()) {
if (b.getIconView() == null) {
@@ -1267,6 +1261,9 @@
new RelativeStackPosition(
mPositioner.getRestingPosition(),
mStackAnimationController.getAllowableStackPositionRegion()));
+ if (mIsExpanded) {
+ updateExpandedView();
+ }
}
@Override
@@ -1816,7 +1813,7 @@
}
mExpandedViewContainer.setTranslationX(0f);
- mExpandedViewContainer.setTranslationY(getExpandedViewY());
+ mExpandedViewContainer.setTranslationY(mPositioner.getExpandedViewY());
mExpandedViewContainer.setAlpha(1f);
int index;
@@ -1865,7 +1862,7 @@
1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT,
1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT,
bubbleWillBeAt + mBubbleSize / 2f,
- getExpandedViewY());
+ mPositioner.getExpandedViewY());
}
mExpandedViewContainer.setAnimationMatrix(mExpandedViewContainerMatrix);
@@ -1969,7 +1966,7 @@
mExpandedViewContainerMatrix.setScale(
1f, 1f,
expandingFromBubbleAt + mBubbleSize / 2f,
- getExpandedViewY());
+ mPositioner.getExpandedViewY());
}
mExpandedViewAlphaAnimator.reverse();
@@ -2075,7 +2072,7 @@
1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT,
1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT,
expandingFromBubbleDestination + mBubbleSize / 2f,
- getExpandedViewY());
+ mPositioner.getExpandedViewY());
}
mExpandedViewContainer.setAnimationMatrix(mExpandedViewContainerMatrix);
@@ -2313,18 +2310,6 @@
: 0f);
}
- /**
- * Calculates the y position of the expanded view when it is expanded.
- */
- float getExpandedViewY() {
- final int top = mPositioner.getAvailableRect().top;
- if (mPositioner.showBubblesVertically()) {
- return top + mExpandedViewPadding;
- } else {
- return top + mBubbleSize + mBubblePaddingTop;
- }
- }
-
private boolean shouldShowFlyout(Bubble bubble) {
Bubble.FlyoutMessage flyoutMessage = bubble.getFlyoutMessage();
final BadgedImageView bubbleView = bubble.getIconView();
@@ -2697,24 +2682,16 @@
if (DEBUG_BUBBLE_STACK_VIEW) {
Log.d(TAG, "updateExpandedView: mIsExpanded=" + mIsExpanded);
}
-
- // Need to update the padding around the view for any insets
- Insets insets = mPositioner.getInsets();
- int leftPadding = insets.left + mExpandedViewPadding;
- int rightPadding = insets.right + mExpandedViewPadding;
- if (mPositioner.showBubblesVertically()) {
- if (!mStackAnimationController.isStackOnLeftSide()) {
- rightPadding += mPointerHeight + mBubbleSize;
- } else {
- leftPadding += mPointerHeight + mBubbleSize;
- }
- }
- mExpandedViewContainer.setPadding(leftPadding, 0, rightPadding, 0);
+ boolean isOverflowExpanded = mExpandedBubble != null
+ && mBubbleOverflow.KEY.equals(mExpandedBubble.getKey());
+ int[] paddings = mPositioner.getExpandedViewPadding(
+ mStackAnimationController.isStackOnLeftSide(), isOverflowExpanded);
+ mExpandedViewContainer.setPadding(paddings[0], 0, paddings[1], 0);
if (mIsExpansionAnimating) {
mExpandedViewContainer.setVisibility(mIsExpanded ? VISIBLE : GONE);
}
if (mExpandedBubble != null && mExpandedBubble.getExpandedView() != null) {
- mExpandedViewContainer.setTranslationY(getExpandedViewY());
+ mExpandedViewContainer.setTranslationY(mPositioner.getExpandedViewY());
mExpandedViewContainer.setTranslationX(0f);
mExpandedBubble.getExpandedView().updateView(
mExpandedViewContainer.getLocationOnScreen());
@@ -2755,13 +2732,14 @@
return;
}
float bubblePosition = mExpandedAnimationController.getBubbleXOrYForOrientation(index);
+ float expandedViewY = mPositioner.getExpandedViewY();
if (mPositioner.showBubblesVertically()) {
float x = mStackOnLeftOrWillBe
? mPositioner.getAvailableRect().left
: mPositioner.getAvailableRect().right
- mExpandedViewContainer.getPaddingRight()
- mPointerHeight;
- float bubbleCenter = bubblePosition - getExpandedViewY() + (mBubbleSize / 2f);
+ float bubbleCenter = bubblePosition - expandedViewY + (mBubbleSize / 2f);
mExpandedBubble.getExpandedView().setPointerPosition(
x,
bubbleCenter,
@@ -2771,7 +2749,7 @@
float bubbleCenter = bubblePosition + (mBubbleSize / 2f);
mExpandedBubble.getExpandedView().setPointerPosition(
bubbleCenter,
- getExpandedViewY(),
+ expandedViewY,
false,
mStackOnLeftOrWillBe);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationController.java
index 18aaa96..48bd894 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationController.java
@@ -16,7 +16,6 @@
package com.android.wm.shell.bubbles.animation;
-import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Path;
import android.graphics.PointF;
@@ -142,6 +141,7 @@
updateResources();
mExpandedViewPadding = expandedViewPadding;
mOnBubbleAnimatedOutAction = onBubbleAnimatedOutAction;
+ mCollapsePoint = mPositioner.getDefaultStartPosition();
}
/**
@@ -528,17 +528,34 @@
startOrUpdatePathAnimation(true /* expanding */);
} else if (mAnimatingCollapse) {
startOrUpdatePathAnimation(false /* expanding */);
+ } else if (mPositioner.showBubblesVertically()) {
+ child.setTranslationY(getBubbleXOrYForOrientation(index));
+ if (!mPreparingToCollapse) {
+ // Only animate if we're not collapsing as that animation will handle placing the
+ // new bubble in the stacked position.
+ Rect availableRect = mPositioner.getAvailableRect();
+ boolean onLeft = mCollapsePoint != null
+ && mCollapsePoint.x < (availableRect.width() / 2f);
+ float fromX = onLeft
+ ? -mBubbleSizePx * ANIMATE_TRANSLATION_FACTOR
+ : availableRect.right + mBubbleSizePx * ANIMATE_TRANSLATION_FACTOR;
+ float toX = onLeft
+ ? availableRect.left + mExpandedViewPadding
+ : availableRect.right - mBubbleSizePx - mExpandedViewPadding;
+ animationForChild(child)
+ .translationX(fromX, toX)
+ .start();
+ updateBubblePositions();
+ }
} else {
child.setTranslationX(getBubbleXOrYForOrientation(index));
-
- // If we're preparing to collapse, don't start animations since the collapse animation
- // will take over and animate the new bubble into the correct (stacked) position.
if (!mPreparingToCollapse) {
+ // Only animate if we're not collapsing as that animation will handle placing the
+ // new bubble in the stacked position.
+ float toY = getExpandedY();
+ float fromY = getExpandedY() - mBubbleSizePx * ANIMATE_TRANSLATION_FACTOR;
animationForChild(child)
- .translationY(
- getExpandedY()
- - mBubbleSizePx * ANIMATE_TRANSLATION_FACTOR, /* from */
- getExpandedY() /* to */)
+ .translationY(fromY, toY)
.start();
updateBubblePositions();
}
@@ -617,15 +634,16 @@
}
}
+ // TODO - could move to method on bubblePositioner if mSpaceBetweenBubbles gets moved
/**
* When bubbles are expanded in portrait, they display at the top of the screen in a horizontal
- * row. When in landscape, they show at the left or right side in a vertical row. This method
- * accounts for screen orientation and will return an x or y value for the position of the
- * bubble in the row.
+ * row. When in landscape or on a large screen, they show at the left or right side in a
+ * vertical row. This method accounts for screen orientation and will return an x or y value
+ * for the position of the bubble in the row.
*
* @param index Bubble index in row.
- * @return the y position of the bubble if {@link Configuration#ORIENTATION_LANDSCAPE} and the
- * x position if {@link Configuration#ORIENTATION_PORTRAIT}.
+ * @return the y position of the bubble if showing vertically and the x position if showing
+ * horizontally.
*/
public float getBubbleXOrYForOrientation(int index) {
if (mLayout == null) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/StackAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/StackAnimationController.java
index 56fe126..578f87f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/StackAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/StackAnimationController.java
@@ -958,17 +958,26 @@
if (!isActiveController()) {
return;
}
- v.setTranslationX(mStackPosition.x);
+
final float yOffset =
getOffsetForChainedPropertyAnimation(DynamicAnimation.TRANSLATION_Y);
- final float endY = mStackPosition.y + yOffset * index;
- final float startY = endY + NEW_BUBBLE_START_Y;
- v.setTranslationY(startY);
+ float endY = mStackPosition.y + yOffset * index;
+ float endX = mStackPosition.x;
+ if (mPositioner.showBubblesVertically()) {
+ v.setTranslationY(endY);
+ final float startX = isStackOnLeftSide()
+ ? endX - NEW_BUBBLE_START_Y
+ : endX + NEW_BUBBLE_START_Y;
+ v.setTranslationX(startX);
+ } else {
+ v.setTranslationX(mStackPosition.x);
+ final float startY = endY + NEW_BUBBLE_START_Y;
+ v.setTranslationY(startY);
+ }
v.setScaleX(NEW_BUBBLE_START_SCALE);
v.setScaleY(NEW_BUBBLE_START_SCALE);
v.setAlpha(0f);
final ViewPropertyAnimator animator = v.animate()
- .translationY(endY)
.scaleX(1f)
.scaleY(1f)
.alpha(1f)
@@ -977,6 +986,11 @@
v.setTag(R.id.reorder_animator_tag, null);
});
v.setTag(R.id.reorder_animator_tag, animator);
+ if (mPositioner.showBubblesVertically()) {
+ animator.translationX(endX);
+ } else {
+ animator.translationY(endY);
+ }
}
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipSnapAlgorithm.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipSnapAlgorithm.java
index 0528e4d..dd30137 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipSnapAlgorithm.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipSnapAlgorithm.java
@@ -109,13 +109,14 @@
* consideration.
*/
public void applySnapFraction(Rect stackBounds, Rect movementBounds, float snapFraction,
- @PipBoundsState.StashType int stashType, int stashOffset, Rect displayBounds) {
+ @PipBoundsState.StashType int stashType, int stashOffset, Rect displayBounds,
+ Rect insetBounds) {
applySnapFraction(stackBounds, movementBounds, snapFraction);
if (stashType != STASH_TYPE_NONE) {
stackBounds.offsetTo(stashType == STASH_TYPE_LEFT
- ? stashOffset - stackBounds.width()
- : displayBounds.right - stashOffset,
+ ? stashOffset - stackBounds.width() + insetBounds.left
+ : displayBounds.right - stashOffset - insetBounds.right,
stackBounds.top);
}
}
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 17cde73..9cf0b72 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
@@ -18,6 +18,8 @@
import static android.view.WindowManager.SHELL_ROOT_LAYER_PIP;
+import static com.android.wm.shell.pip.phone.PipMenuView.ANIM_TYPE_HIDE;
+
import android.annotation.Nullable;
import android.app.RemoteAction;
import android.content.Context;
@@ -397,26 +399,26 @@
* Hides the menu view.
*/
public void hideMenu() {
- hideMenu(true /* animate */, true /* resize */);
+ hideMenu(ANIM_TYPE_HIDE, true /* resize */);
}
/**
* Hides the menu view.
*
- * @param animate whether to animate the menu fadeout
+ * @param animationType the animation type to use upon hiding the menu
* @param resize whether or not to resize the PiP with the state change
*/
- public void hideMenu(boolean animate, boolean resize) {
+ public void hideMenu(@PipMenuView.AnimationType int animationType, boolean resize) {
final boolean isMenuVisible = isMenuVisible();
if (DEBUG) {
Log.d(TAG, "hideMenu() state=" + mMenuState
+ " isMenuVisible=" + isMenuVisible
- + " animate=" + animate
+ + " animationType=" + animationType
+ " resize=" + resize
+ " callers=\n" + Debug.getCallers(5, " "));
}
if (isMenuVisible) {
- mPipMenuView.hideMenu(animate, resize);
+ mPipMenuView.hideMenu(resize, animationType);
}
}
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 b881fea..fa5caf0 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
@@ -464,7 +464,8 @@
pipSnapAlgorithm.applySnapFraction(postChangeStackBounds, postChangeMovementBounds,
snapFraction, mPipBoundsState.getStashedState(),
mPipBoundsState.getStashOffset(),
- mPipBoundsState.getDisplayBounds());
+ mPipBoundsState.getDisplayBounds(),
+ mPipBoundsState.getDisplayLayout().stableInsets());
mTouchHandler.getMotionHelper().movePip(postChangeStackBounds);
} else {
@@ -668,7 +669,8 @@
postChangeStackBounds, false /* adjustForIme */);
pipSnapAlgorithm.applySnapFraction(postChangeStackBounds, postChangeMovementBounds,
snapFraction, mPipBoundsState.getStashedState(), mPipBoundsState.getStashOffset(),
- mPipBoundsState.getDisplayBounds());
+ mPipBoundsState.getDisplayBounds(),
+ mPipBoundsState.getDisplayLayout().stableInsets());
mPipBoundsAlgorithm.getInsetBounds(outInsetBounds);
outBounds.set(postChangeStackBounds);
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 a57e8cd..2b45346 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
@@ -32,6 +32,7 @@
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
+import android.annotation.IntDef;
import android.app.PendingIntent.CanceledException;
import android.app.RemoteAction;
import android.content.ComponentName;
@@ -64,6 +65,8 @@
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.pip.PipUtils;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
@@ -74,9 +77,26 @@
private static final String TAG = "PipMenuView";
+ private static final int ANIMATION_NONE_DURATION_MS = 0;
+ private static final int ANIMATION_HIDE_DURATION_MS = 125;
+
+ /** No animation performed during menu hide. */
+ public static final int ANIM_TYPE_NONE = 0;
+ /** Fade out the menu until it's invisible. Used when the PIP window remains visible. */
+ public static final int ANIM_TYPE_HIDE = 1;
+ /** Fade out the menu in sync with the PIP window. */
+ public static final int ANIM_TYPE_DISMISS = 2;
+
+ @IntDef(prefix = { "ANIM_TYPE_" }, value = {
+ ANIM_TYPE_NONE,
+ ANIM_TYPE_HIDE,
+ ANIM_TYPE_DISMISS
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface AnimationType {}
+
private static final int INITIAL_DISMISS_DELAY = 3500;
private static final int POST_INTERACTION_DISMISS_DELAY = 2000;
- private static final long MENU_FADE_DURATION = 125;
private static final long MENU_SHOW_ON_EXPAND_START_DELAY = 30;
private static final float MENU_BACKGROUND_ALPHA = 0.3f;
@@ -87,6 +107,7 @@
private int mMenuState;
private boolean mAllowMenuTimeout = true;
private boolean mAllowTouches = true;
+ private int mDismissFadeOutDurationMs;
private final List<RemoteAction> mActions = new ArrayList<>();
@@ -167,6 +188,8 @@
mPipMenuIconsAlgorithm = new PipMenuIconsAlgorithm(mContext);
mPipMenuIconsAlgorithm.bindViews((ViewGroup) mViewRoot, (ViewGroup) mTopEndContainer,
mResizeHandle, mSettingsButton, mDismissButton);
+ mDismissFadeOutDurationMs = context.getResources()
+ .getInteger(R.integer.config_pipExitAnimationDuration);
initAccessibility();
}
@@ -258,7 +281,7 @@
mMenuContainerAnimator.playTogether(dismissAnim, resizeAnim);
}
mMenuContainerAnimator.setInterpolator(Interpolators.ALPHA_IN);
- mMenuContainerAnimator.setDuration(MENU_FADE_DURATION);
+ mMenuContainerAnimator.setDuration(ANIMATION_HIDE_DURATION_MS);
if (allowMenuTimeout) {
mMenuContainerAnimator.addListener(new AnimatorListenerAdapter() {
@Override
@@ -320,17 +343,18 @@
hideMenu(null);
}
- void hideMenu(boolean animate, boolean resize) {
- hideMenu(null, true /* notifyMenuVisibility */, animate, resize);
- }
-
void hideMenu(Runnable animationEndCallback) {
- hideMenu(animationEndCallback, true /* notifyMenuVisibility */, true /* animate */,
- true /* resize */);
+ hideMenu(animationEndCallback, true /* notifyMenuVisibility */, true /* resize */,
+ ANIM_TYPE_HIDE);
}
- private void hideMenu(final Runnable animationFinishedRunnable, boolean notifyMenuVisibility,
- boolean animate, boolean resize) {
+ void hideMenu(boolean resize, @AnimationType int animationType) {
+ hideMenu(null /* animationFinishedRunnable */, true /* notifyMenuVisibility */, resize,
+ animationType);
+ }
+
+ void hideMenu(final Runnable animationFinishedRunnable, boolean notifyMenuVisibility,
+ boolean resize, @AnimationType int animationType) {
if (mMenuState != MENU_STATE_NONE) {
cancelDelayedHide();
if (notifyMenuVisibility) {
@@ -348,7 +372,7 @@
mResizeHandle.getAlpha(), 0f);
mMenuContainerAnimator.playTogether(menuAnim, settingsAnim, dismissAnim, resizeAnim);
mMenuContainerAnimator.setInterpolator(Interpolators.ALPHA_OUT);
- mMenuContainerAnimator.setDuration(animate ? MENU_FADE_DURATION : 0);
+ mMenuContainerAnimator.setDuration(getFadeOutDuration(animationType));
mMenuContainerAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
@@ -478,19 +502,17 @@
private void expandPip() {
// Do not notify menu visibility when hiding the menu, the controller will do this when it
// handles the message
- hideMenu(mController::onPipExpand, false /* notifyMenuVisibility */, true /* animate */,
- true /* resize */);
+ hideMenu(mController::onPipExpand, false /* notifyMenuVisibility */, true /* resize */,
+ ANIM_TYPE_HIDE);
}
private void dismissPip() {
- // Since tapping on the close-button invokes a double-tap wait callback in PipTouchHandler,
- // we want to disable animating the fadeout animation of the buttons in order to call on
- // PipTouchHandler#onPipDismiss fast enough.
- final boolean animate = mMenuState != MENU_STATE_CLOSE;
- // Do not notify menu visibility when hiding the menu, the controller will do this when it
- // handles the message
- hideMenu(mController::onPipDismiss, false /* notifyMenuVisibility */, animate,
- true /* resize */);
+ if (mMenuState != MENU_STATE_NONE) {
+ // Do not call hideMenu() directly. Instead, let the menu controller handle it just as
+ // any other dismissal that will update the touch state and fade out the PIP task
+ // and the menu view at the same time.
+ mController.onPipDismiss();
+ }
}
private void showSettings() {
@@ -514,4 +536,17 @@
mMainExecutor.removeCallbacks(mHideMenuRunnable);
mMainExecutor.executeDelayed(mHideMenuRunnable, recommendedTimeout);
}
+
+ private long getFadeOutDuration(@AnimationType int animationType) {
+ switch (animationType) {
+ case ANIM_TYPE_NONE:
+ return ANIMATION_NONE_DURATION_MS;
+ case ANIM_TYPE_HIDE:
+ return ANIMATION_HIDE_DURATION_MS;
+ case ANIM_TYPE_DISMISS:
+ return mDismissFadeOutDurationMs;
+ default:
+ throw new IllegalStateException("Invalid animation type " + animationType);
+ }
+ }
}
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 1062561..9401cd6 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
@@ -22,6 +22,8 @@
import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_EXPAND_OR_UNEXPAND;
import static com.android.wm.shell.pip.PipBoundsState.STASH_TYPE_NONE;
+import static com.android.wm.shell.pip.phone.PipMenuView.ANIM_TYPE_DISMISS;
+import static com.android.wm.shell.pip.phone.PipMenuView.ANIM_TYPE_NONE;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -336,7 +338,7 @@
+ " callers=\n" + Debug.getCallers(5, " "));
}
cancelPhysicsAnimation();
- mMenuController.hideMenu(false /* animate */, false /* resize */);
+ mMenuController.hideMenu(ANIM_TYPE_NONE, false /* resize */);
mPipTaskOrganizer.exitPip(skipAnimation ? 0 : LEAVE_PIP_DURATION);
}
@@ -349,7 +351,7 @@
Log.d(TAG, "removePip: callers=\n" + Debug.getCallers(5, " "));
}
cancelPhysicsAnimation();
- mMenuController.hideMenu(true /* animate*/, false /* resize */);
+ mMenuController.hideMenu(ANIM_TYPE_DISMISS, false /* resize */);
mPipTaskOrganizer.removePip();
}
@@ -406,11 +408,14 @@
.flingThenSpring(
FloatProperties.RECT_Y, velocityY, mFlingConfigY, mSpringConfig);
+ final Rect insetBounds = mPipBoundsState.getDisplayLayout().stableInsets();
final float leftEdge = isStash
? mPipBoundsState.getStashOffset() - mPipBoundsState.getBounds().width()
+ + insetBounds.left
: mPipBoundsState.getMovementBounds().left;
final float rightEdge = isStash
? mPipBoundsState.getDisplayBounds().right - mPipBoundsState.getStashOffset()
+ - insetBounds.right
: mPipBoundsState.getMovementBounds().right;
final float xEndValue = velocityX < 0 ? leftEdge : rightEdge;
@@ -483,7 +488,8 @@
mSnapAlgorithm.applySnapFraction(normalBounds, normalMovementBounds, savedSnapFraction,
mPipBoundsState.getStashedState(), mPipBoundsState.getStashOffset(),
- mPipBoundsState.getDisplayBounds());
+ mPipBoundsState.getDisplayBounds(),
+ mPipBoundsState.getDisplayLayout().stableInsets());
if (immediate) {
movePip(normalBounds);
@@ -529,10 +535,13 @@
mFlingConfigY = new PhysicsAnimator.FlingConfig(DEFAULT_FRICTION,
mPipBoundsState.getMovementBounds().top,
mPipBoundsState.getMovementBounds().bottom);
+ final Rect insetBounds = mPipBoundsState.getDisplayLayout().stableInsets();
mStashConfigX = new PhysicsAnimator.FlingConfig(
DEFAULT_FRICTION,
- mPipBoundsState.getStashOffset() - mPipBoundsState.getBounds().width(),
- mPipBoundsState.getDisplayBounds().right - mPipBoundsState.getStashOffset());
+ mPipBoundsState.getStashOffset() - mPipBoundsState.getBounds().width()
+ + insetBounds.left,
+ mPipBoundsState.getDisplayBounds().right - mPipBoundsState.getStashOffset()
+ - insetBounds.right);
}
private void startBoundsAnimator(float toX, float toY) {
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 c2ec1c5..8726ee7 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
@@ -21,6 +21,7 @@
import static com.android.internal.policy.TaskResizingAlgorithm.CTRL_NONE;
import static com.android.internal.policy.TaskResizingAlgorithm.CTRL_RIGHT;
import static com.android.internal.policy.TaskResizingAlgorithm.CTRL_TOP;
+import static com.android.wm.shell.pip.phone.PipMenuView.ANIM_TYPE_NONE;
import android.content.Context;
import android.content.res.Resources;
@@ -471,7 +472,7 @@
}
if (mThresholdCrossed) {
if (mPhonePipMenuController.isMenuVisible()) {
- mPhonePipMenuController.hideMenu(false /* animate */,
+ mPhonePipMenuController.hideMenu(ANIM_TYPE_NONE,
false /* resize */);
}
final Rect currentPipBounds = mPipBoundsState.getBounds();
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 6d96312..0a0798e 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
@@ -25,6 +25,7 @@
import static com.android.wm.shell.pip.phone.PhonePipMenuController.MENU_STATE_CLOSE;
import static com.android.wm.shell.pip.phone.PhonePipMenuController.MENU_STATE_FULL;
import static com.android.wm.shell.pip.phone.PhonePipMenuController.MENU_STATE_NONE;
+import static com.android.wm.shell.pip.phone.PipMenuView.ANIM_TYPE_NONE;
import android.annotation.NonNull;
import android.annotation.SuppressLint;
@@ -881,7 +882,7 @@
&& mPipBoundsState.getBounds().height()
< mPipBoundsState.getMaxSize().y;
if (mMenuController.isMenuVisible()) {
- mMenuController.hideMenu(false /* animate */, false /* resize */);
+ mMenuController.hideMenu(ANIM_TYPE_NONE, false /* resize */);
}
if (toExpand) {
mPipResizeGestureHandler.setUserResizeBounds(mPipBoundsState.getBounds());
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenNotSupportNonResizable.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenNotSupportNonResizable.kt
index 58e9204..04f97c8 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenNotSupportNonResizable.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenNotSupportNonResizable.kt
@@ -16,7 +16,7 @@
package com.android.wm.shell.flicker.legacysplitscreen
-import android.platform.test.annotations.Postsubmit
+import android.platform.test.annotations.Presubmit
import android.provider.Settings
import android.view.Surface
import androidx.test.filters.RequiresDevice
@@ -44,7 +44,6 @@
*
* To run this test: `atest WMShellFlickerTests:EnterSplitScreenNotSupportNonResizable`
*/
-@Postsubmit
@RequiresDevice
@RunWith(Parameterized::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@@ -94,6 +93,7 @@
prevSupportNonResizableInMultiWindow)
}
+ @Presubmit
@Test
fun dockedStackDividerIsInvisible() = testSpec.dockedStackDividerIsInvisible()
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenSupportNonResizable.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenSupportNonResizable.kt
index 91ca7c1..2832bb4 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenSupportNonResizable.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenSupportNonResizable.kt
@@ -16,7 +16,7 @@
package com.android.wm.shell.flicker.legacysplitscreen
-import android.platform.test.annotations.Postsubmit
+import android.platform.test.annotations.Presubmit
import android.provider.Settings
import android.view.Surface
import androidx.test.filters.RequiresDevice
@@ -43,7 +43,6 @@
*
* To run this test: `atest WMShellFlickerTests:EnterSplitScreenSupportNonResizable`
*/
-@Postsubmit
@RequiresDevice
@RunWith(Parameterized::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@@ -91,9 +90,11 @@
prevSupportNonResizableInMultiWindow)
}
+ @Presubmit
@Test
fun dockedStackDividerIsVisible() = testSpec.dockedStackDividerIsVisible()
+ @Presubmit
@Test
fun appWindowIsVisible() {
testSpec.assertWmEnd {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenFromIntentNotSupportNonResizable.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenFromIntentNotSupportNonResizable.kt
index 968aff1..32afd19 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenFromIntentNotSupportNonResizable.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenFromIntentNotSupportNonResizable.kt
@@ -16,7 +16,7 @@
package com.android.wm.shell.flicker.legacysplitscreen
-import android.platform.test.annotations.Postsubmit
+import android.platform.test.annotations.Presubmit
import android.provider.Settings
import android.view.Surface
import androidx.test.filters.RequiresDevice
@@ -46,7 +46,6 @@
* support non-resizable in multi window, it should trigger exit split screen.
* To run this test: `atest WMShellFlickerTests:LegacySplitScreenFromIntentNotSupportNonResizable`
*/
-@Postsubmit
@RequiresDevice
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@@ -95,25 +94,31 @@
prevSupportNonResizableInMultiWindow)
}
+ @Presubmit
@Test
fun resizableAppLayerBecomesInvisible() =
testSpec.layerBecomesInvisible(splitScreenApp.defaultWindowName)
+ @Presubmit
@Test
fun nonResizableAppLayerBecomesVisible() =
testSpec.layerBecomesVisible(nonResizeableApp.defaultWindowName)
+ @Presubmit
@Test
fun resizableAppWindowBecomesInvisible() =
testSpec.appWindowBecomesInVisible(splitScreenApp.defaultWindowName)
+ @Presubmit
@Test
fun nonResizableAppWindowBecomesVisible() =
testSpec.appWindowBecomesVisible(nonResizeableApp.defaultWindowName)
+ @Presubmit
@Test
fun dockedStackDividerIsInvisibleAtEnd() = testSpec.dockedStackDividerIsInvisible()
+ @Presubmit
@Test
fun onlyNonResizableAppWindowIsVisibleAtEnd() {
testSpec.assertWmEnd {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenFromIntentSupportNonResizable.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenFromIntentSupportNonResizable.kt
index 8d20673..af30758 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenFromIntentSupportNonResizable.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenFromIntentSupportNonResizable.kt
@@ -16,7 +16,7 @@
package com.android.wm.shell.flicker.legacysplitscreen
-import android.platform.test.annotations.Postsubmit
+import android.platform.test.annotations.Presubmit
import android.provider.Settings
import android.view.Surface
import androidx.test.filters.RequiresDevice
@@ -44,7 +44,6 @@
* non-resizable in multi window, it should show the non-resizable app in split screen.
* To run this test: `atest WMShellFlickerTests:LegacySplitScreenFromIntentSupportNonResizable`
*/
-@Postsubmit
@RequiresDevice
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@@ -93,17 +92,21 @@
prevSupportNonResizableInMultiWindow)
}
+ @Presubmit
@Test
fun nonResizableAppLayerBecomesVisible() =
testSpec.layerBecomesVisible(nonResizeableApp.defaultWindowName)
+ @Presubmit
@Test
fun nonResizableAppWindowBecomesVisible() =
testSpec.appWindowBecomesVisible(nonResizeableApp.defaultWindowName)
+ @Presubmit
@Test
fun dockedStackDividerIsVisibleAtEnd() = testSpec.dockedStackDividerIsVisible()
+ @Presubmit
@Test
fun bothAppsWindowsAreVisibleAtEnd() {
testSpec.assertWmEnd {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenFromRecentNotSupportNonResizable.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenFromRecentNotSupportNonResizable.kt
index 4e291d9..8c62758 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenFromRecentNotSupportNonResizable.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenFromRecentNotSupportNonResizable.kt
@@ -16,7 +16,7 @@
package com.android.wm.shell.flicker.legacysplitscreen
-import android.platform.test.annotations.Postsubmit
+import android.platform.test.annotations.Presubmit
import android.provider.Settings
import android.view.Surface
import androidx.test.filters.RequiresDevice
@@ -47,7 +47,6 @@
* not support non-resizable in multi window, it should trigger exit split screen.
* To run this test: `atest WMShellFlickerTests:LegacySplitScreenFromRecentNotSupportNonResizable`
*/
-@Postsubmit
@RequiresDevice
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@@ -96,25 +95,31 @@
prevSupportNonResizableInMultiWindow)
}
+ @Presubmit
@Test
fun resizableAppLayerBecomesInvisible() =
testSpec.layerBecomesInvisible(splitScreenApp.defaultWindowName)
+ @Presubmit
@Test
fun nonResizableAppLayerBecomesVisible() =
testSpec.layerBecomesVisible(nonResizeableApp.defaultWindowName)
+ @Presubmit
@Test
fun resizableAppWindowBecomesInvisible() =
testSpec.appWindowBecomesInVisible(splitScreenApp.defaultWindowName)
+ @Presubmit
@Test
fun nonResizableAppWindowBecomesVisible() =
testSpec.appWindowBecomesVisible(nonResizeableApp.defaultWindowName)
+ @Presubmit
@Test
fun dockedStackDividerIsInvisibleAtEnd() = testSpec.dockedStackDividerIsInvisible()
+ @Presubmit
@Test
fun onlyNonResizableAppWindowIsVisibleAtEnd() {
testSpec.assertWmEnd {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenFromRecentSupportNonResizable.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenFromRecentSupportNonResizable.kt
index 880dc55..5b48f8a 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenFromRecentSupportNonResizable.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenFromRecentSupportNonResizable.kt
@@ -16,7 +16,7 @@
package com.android.wm.shell.flicker.legacysplitscreen
-import android.platform.test.annotations.Postsubmit
+import android.platform.test.annotations.Presubmit
import android.provider.Settings
import android.view.Surface
import androidx.test.filters.RequiresDevice
@@ -45,7 +45,6 @@
* supports non-resizable in multi window, it should show the non-resizable app in split screen.
* To run this test: `atest WMShellFlickerTests:LegacySplitScreenFromRecentSupportNonResizable`
*/
-@Postsubmit
@RequiresDevice
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@@ -94,17 +93,21 @@
prevSupportNonResizableInMultiWindow)
}
+ @Presubmit
@Test
fun nonResizableAppLayerBecomesVisible() =
testSpec.layerBecomesVisible(nonResizeableApp.defaultWindowName)
+ @Presubmit
@Test
fun nonResizableAppWindowBecomesVisible() =
testSpec.appWindowBecomesVisible(nonResizeableApp.defaultWindowName)
+ @Presubmit
@Test
fun dockedStackDividerIsVisibleAtEnd() = testSpec.dockedStackDividerIsVisible()
+ @Presubmit
@Test
fun bothAppsWindowsAreVisibleAtEnd() {
testSpec.assertWmEnd {
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipSnapAlgorithmTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipSnapAlgorithmTest.java
index dcee2e1..b9226d2 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipSnapAlgorithmTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipSnapAlgorithmTest.java
@@ -38,6 +38,8 @@
private static final int DEFAULT_STASH_OFFSET = 32;
private static final Rect DISPLAY_BOUNDS = new Rect(0, 0, 2000, 2000);
private static final Rect STACK_BOUNDS_CENTERED = new Rect(900, 900, 1100, 1100);
+ private static final Rect INSET_BOUNDS_EMPTY = new Rect(0, 0, 0, 0);
+ private static final Rect INSET_BOUNDS_RIGHT = new Rect(0, 0, 200, 0);
private static final Rect MOVEMENT_BOUNDS = new Rect(0, 0,
DISPLAY_BOUNDS.width() - STACK_BOUNDS_CENTERED.width(),
DISPLAY_BOUNDS.width() - STACK_BOUNDS_CENTERED.width());
@@ -99,7 +101,8 @@
final Rect bounds = new Rect(STACK_BOUNDS_CENTERED);
mPipSnapAlgorithm.applySnapFraction(bounds, MOVEMENT_BOUNDS, snapFraction,
- PipBoundsState.STASH_TYPE_NONE, DEFAULT_STASH_OFFSET, DISPLAY_BOUNDS);
+ PipBoundsState.STASH_TYPE_NONE, DEFAULT_STASH_OFFSET, DISPLAY_BOUNDS,
+ INSET_BOUNDS_EMPTY);
assertEquals(MOVEMENT_BOUNDS.right, bounds.left);
assertEquals(MOVEMENT_BOUNDS.bottom, bounds.top);
@@ -111,7 +114,8 @@
final Rect bounds = new Rect(STACK_BOUNDS_CENTERED);
mPipSnapAlgorithm.applySnapFraction(bounds, MOVEMENT_BOUNDS, snapFraction,
- PipBoundsState.STASH_TYPE_LEFT, DEFAULT_STASH_OFFSET, DISPLAY_BOUNDS);
+ PipBoundsState.STASH_TYPE_LEFT, DEFAULT_STASH_OFFSET, DISPLAY_BOUNDS,
+ INSET_BOUNDS_EMPTY);
final int offBoundsWidth = bounds.width() - DEFAULT_STASH_OFFSET;
assertEquals(MOVEMENT_BOUNDS.left - offBoundsWidth, bounds.left);
@@ -124,13 +128,28 @@
final Rect bounds = new Rect(STACK_BOUNDS_CENTERED);
mPipSnapAlgorithm.applySnapFraction(bounds, MOVEMENT_BOUNDS, snapFraction,
- PipBoundsState.STASH_TYPE_RIGHT, DEFAULT_STASH_OFFSET, DISPLAY_BOUNDS);
+ PipBoundsState.STASH_TYPE_RIGHT, DEFAULT_STASH_OFFSET, DISPLAY_BOUNDS,
+ INSET_BOUNDS_EMPTY);
assertEquals(DISPLAY_BOUNDS.right - DEFAULT_STASH_OFFSET, bounds.left);
assertEquals(MOVEMENT_BOUNDS.bottom, bounds.top);
}
@Test
+ public void testApplySnapFraction_stashedRight_withInset() {
+ final float snapFraction = 2f;
+ final Rect bounds = new Rect(STACK_BOUNDS_CENTERED);
+
+ mPipSnapAlgorithm.applySnapFraction(bounds, MOVEMENT_BOUNDS, snapFraction,
+ PipBoundsState.STASH_TYPE_RIGHT, DEFAULT_STASH_OFFSET, DISPLAY_BOUNDS,
+ INSET_BOUNDS_RIGHT);
+
+ assertEquals(DISPLAY_BOUNDS.right - DEFAULT_STASH_OFFSET - INSET_BOUNDS_RIGHT.right,
+ bounds.left);
+ assertEquals(MOVEMENT_BOUNDS.bottom, bounds.top);
+ }
+
+ @Test
public void testSnapRectToClosestEdge_rightEdge() {
final Rect bounds = new Rect(STACK_BOUNDS_CENTERED);
// Move the centered rect slightly to the right side.
@@ -183,7 +202,8 @@
final Rect bounds = new Rect(STACK_BOUNDS_CENTERED);
// Stash it on the left side.
mPipSnapAlgorithm.applySnapFraction(bounds, MOVEMENT_BOUNDS, 3.5f,
- PipBoundsState.STASH_TYPE_LEFT, DEFAULT_STASH_OFFSET, DISPLAY_BOUNDS);
+ PipBoundsState.STASH_TYPE_LEFT, DEFAULT_STASH_OFFSET, DISPLAY_BOUNDS,
+ INSET_BOUNDS_EMPTY);
mPipSnapAlgorithm.snapRectToClosestEdge(bounds, MOVEMENT_BOUNDS, bounds,
PipBoundsState.STASH_TYPE_LEFT);
diff --git a/libs/androidfw/PosixUtils.cpp b/libs/androidfw/PosixUtils.cpp
index f1ab149..4ec525a 100644
--- a/libs/androidfw/PosixUtils.cpp
+++ b/libs/androidfw/PosixUtils.cpp
@@ -72,7 +72,8 @@
argv0[i] = argv[i].c_str();
}
argv0[argv.size()] = nullptr;
- switch (fork()) {
+ int pid = fork();
+ switch (pid) {
case -1: // error
free(argv0);
PLOG(ERROR) << "fork";
@@ -104,8 +105,10 @@
close(stdout[1]);
close(stderr[1]);
int status;
- wait(&status);
+ waitpid(pid, &status, 0);
if (!WIFEXITED(status)) {
+ close(stdout[0]);
+ close(stderr[0]);
return nullptr;
}
std::unique_ptr<ProcResult> result(new ProcResult());
diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java
index 232de0b..fbf7def 100644
--- a/media/java/android/media/MediaRouter2.java
+++ b/media/java/android/media/MediaRouter2.java
@@ -180,7 +180,7 @@
// SecurityException will be thrown if there's no permission.
serviceBinder.enforceMediaContentControlPermission();
} catch (RemoteException e) {
- Log.e(TAG, "Unable to check MEDIA_CONTENT_CONTROL permission.");
+ e.rethrowFromSystemServer();
}
PackageManager pm = context.getPackageManager();
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index 4bdbe36..657c9ef 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -1737,8 +1737,6 @@
fId = static_cast<uint64_t>(id);
}
- filterClient->getAvSharedHandleInfo();
-
JNIEnv *env = AndroidRuntime::getJNIEnv();
jobject filterObj =
env->NewObject(
diff --git a/media/jni/tuner/FilterClient.cpp b/media/jni/tuner/FilterClient.cpp
index dc1d8b7..324c09a 100644
--- a/media/jni/tuner/FilterClient.cpp
+++ b/media/jni/tuner/FilterClient.cpp
@@ -63,6 +63,7 @@
mAvSharedHandle = NULL;
mAvSharedMemSize = 0;
mIsMediaFilter = false;
+ mIsPassthroughFilter = false;
mFilterMQ = NULL;
mFilterMQEventFlag = NULL;
}
@@ -84,7 +85,7 @@
SharedHandleInfo FilterClient::getAvSharedHandleInfo() {
handleAvShareMemory();
SharedHandleInfo info{
- .sharedHandle = mIsMediaFilter ? mAvSharedHandle : NULL,
+ .sharedHandle = (mIsMediaFilter && !mIsPassthroughFilter) ? mAvSharedHandle : NULL,
.size = mAvSharedMemSize,
};
@@ -92,13 +93,24 @@
}
Result FilterClient::configure(DemuxFilterSettings configure) {
+ Result res;
+ checkIsPassthroughFilter(configure);
+
if (mTunerFilter != NULL) {
Status s = mTunerFilter->configure(getAidlFilterSettings(configure));
- return ClientHelper::getServiceSpecificErrorCode(s);
+ res = ClientHelper::getServiceSpecificErrorCode(s);
+ if (res == Result::SUCCESS) {
+ getAvSharedHandleInfo();
+ }
+ return res;
}
if (mFilter != NULL) {
- return mFilter->configure(configure);
+ res = mFilter->configure(configure);
+ if (res == Result::SUCCESS) {
+ getAvSharedHandleInfo();
+ }
+ return res;
}
return Result::INVALID_STATE;
@@ -983,11 +995,34 @@
mIsMediaFilter = false;
}
+void FilterClient::checkIsPassthroughFilter(DemuxFilterSettings configure) {
+ if (!mIsMediaFilter) {
+ mIsPassthroughFilter = false;
+ return;
+ }
+
+ if (configure.getDiscriminator() == DemuxFilterSettings::hidl_discriminator::ts) {
+ if (configure.ts().filterSettings.av().isPassthrough) {
+ mIsPassthroughFilter = true;
+ return;
+ }
+ }
+
+ if (configure.getDiscriminator() == DemuxFilterSettings::hidl_discriminator::mmtp) {
+ if (configure.mmtp().filterSettings.av().isPassthrough) {
+ mIsPassthroughFilter = true;
+ return;
+ }
+ }
+
+ mIsPassthroughFilter = false;
+}
+
void FilterClient::handleAvShareMemory() {
if (mAvSharedHandle != NULL) {
return;
}
- if (mTunerFilter != NULL && mIsMediaFilter) {
+ if (mTunerFilter != NULL && mIsMediaFilter && !mIsPassthroughFilter) {
TunerFilterSharedHandleInfo aidlHandleInfo;
Status s = mTunerFilter->getAvSharedHandleInfo(&aidlHandleInfo);
if (ClientHelper::getServiceSpecificErrorCode(s) == Result::SUCCESS) {
@@ -997,7 +1032,7 @@
return;
}
- if (mFilter_1_1 != NULL && mIsMediaFilter) {
+ if (mFilter_1_1 != NULL && mIsMediaFilter && !mIsPassthroughFilter) {
mFilter_1_1->getAvSharedHandle([&](Result r, hidl_handle avMemory, uint64_t avMemSize) {
if (r == Result::SUCCESS) {
mAvSharedHandle = native_handle_clone(avMemory.getNativeHandle());
diff --git a/media/jni/tuner/FilterClient.h b/media/jni/tuner/FilterClient.h
index d032749..5d78bfd 100644
--- a/media/jni/tuner/FilterClient.h
+++ b/media/jni/tuner/FilterClient.h
@@ -241,6 +241,7 @@
Result getFilterMq();
int copyData(int8_t* buffer, int size);
void checkIsMediaFilter(DemuxFilterType type);
+ void checkIsPassthroughFilter(DemuxFilterSettings configure);
void handleAvShareMemory();
void closeAvSharedMemory();
@@ -270,6 +271,7 @@
native_handle_t* mAvSharedHandle;
uint64_t mAvSharedMemSize;
bool mIsMediaFilter;
+ bool mIsPassthroughFilter;
};
} // namespace android
diff --git a/media/jni/tuner/TunerClient.cpp b/media/jni/tuner/TunerClient.cpp
index c9a7e83..e05dba6 100644
--- a/media/jni/tuner/TunerClient.cpp
+++ b/media/jni/tuner/TunerClient.cpp
@@ -326,6 +326,7 @@
// TODO: update Demux, Descrambler.
}
+// TODO: remove after migration to Tuner Service is done.
void TunerClient::updateFrontendResources() {
vector<FrontendId> ids = getFrontendIds();
if (ids.size() == 0) {
@@ -446,6 +447,7 @@
return lnb;
}
+// TODO: remove after migration to Tuner Service is done.
vector<int> TunerClient::getLnbHandles() {
vector<int> lnbHandles;
if (mTuner != NULL) {
@@ -612,12 +614,13 @@
return hidlFrontendInfo;
}
+// TODO: remove after migration to Tuner Service is done.
int TunerClient::getResourceIdFromHandle(int handle, int /*resourceType*/) {
return (handle & 0x00ff0000) >> 16;
}
+// TODO: remove after migration to Tuner Service is done.
int TunerClient::getResourceHandleFromId(int id, int resourceType) {
- // TODO: build up randomly generated id to handle mapping
return (resourceType & 0x000000ff) << 24
| (id << 16)
| (mResourceRequestCount++ & 0xffff);
diff --git a/media/tests/MediaRouter/Android.bp b/media/tests/MediaRouter/Android.bp
index d41bc02..2da6c98 100644
--- a/media/tests/MediaRouter/Android.bp
+++ b/media/tests/MediaRouter/Android.bp
@@ -18,7 +18,9 @@
],
static_libs: [
+ "androidx.test.core",
"androidx.test.rules",
+ "compatibility-device-util-axt",
"mockito-target-minus-junit4",
"testng",
"truth-prebuilt",
diff --git a/media/tests/MediaRouter/AndroidManifest.xml b/media/tests/MediaRouter/AndroidManifest.xml
index 02688d5..018f148 100644
--- a/media/tests/MediaRouter/AndroidManifest.xml
+++ b/media/tests/MediaRouter/AndroidManifest.xml
@@ -19,6 +19,7 @@
<application android:label="@string/app_name">
<uses-library android:name="android.test.runner" />
+ <activity android:name="com.android.mediaroutertest.MediaRouter2ManagerTestActivity" />
<service android:name=".StubMediaRoute2ProviderService"
android:exported="true">
<intent-filter>
diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTest.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTest.java
index eaa4f03..3a34e75 100644
--- a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTest.java
+++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTest.java
@@ -16,7 +16,6 @@
package com.android.mediaroutertest;
-import static android.media.MediaRoute2Info.FEATURE_LIVE_AUDIO;
import static android.media.MediaRoute2Info.FEATURE_REMOTE_PLAYBACK;
import static android.media.MediaRoute2Info.PLAYBACK_VOLUME_FIXED;
import static android.media.MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE;
@@ -61,6 +60,8 @@
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.compatibility.common.util.PollingCheck;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -94,6 +95,7 @@
private MediaRouter2 mRouter2;
private Executor mExecutor;
private String mPackageName;
+ private StubMediaRoute2ProviderService mService;
private final List<MediaRouter2Manager.Callback> mManagerCallbacks = new ArrayList<>();
private final List<RouteCallback> mRouteCallbacks = new ArrayList<>();
@@ -105,7 +107,6 @@
static {
FEATURES_ALL.add(FEATURE_SAMPLE);
FEATURES_ALL.add(FEATURE_SPECIAL);
- FEATURES_ALL.add(FEATURE_LIVE_AUDIO);
FEATURES_SPECIAL.add(FEATURE_SPECIAL);
}
@@ -115,26 +116,53 @@
mContext = InstrumentationRegistry.getTargetContext();
mUiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
mUiAutomation.adoptShellPermissionIdentity(Manifest.permission.MEDIA_CONTENT_CONTROL);
+ MediaRouter2ManagerTestActivity.startActivity(mContext);
+
mManager = MediaRouter2Manager.getInstance(mContext);
+ mManager.startScan();
mRouter2 = MediaRouter2.getInstance(mContext);
+
// If we need to support thread pool executors, change this to thread pool executor.
mExecutor = Executors.newSingleThreadExecutor();
mPackageName = mContext.getPackageName();
+
+ // In order to make the system bind to the test service,
+ // set a non-empty discovery preference while app is in foreground.
+ List<String> features = new ArrayList<>();
+ features.add("A test feature");
+ RouteDiscoveryPreference preference =
+ new RouteDiscoveryPreference.Builder(features, false).build();
+ mRouter2.registerRouteCallback(mExecutor, new RouteCallback() {}, preference);
+
+ new PollingCheck(TIMEOUT_MS) {
+ @Override
+ protected boolean check() {
+ StubMediaRoute2ProviderService service =
+ StubMediaRoute2ProviderService.getInstance();
+ if (service != null) {
+ mService = service;
+ return true;
+ }
+ return false;
+ }
+ }.run();
}
@After
public void tearDown() {
+ mManager.stopScan();
+
// order matters (callbacks should be cleared at the last)
releaseAllSessions();
// unregister callbacks
clearCallbacks();
- StubMediaRoute2ProviderService instance = StubMediaRoute2ProviderService.getInstance();
- if (instance != null) {
- instance.setProxy(null);
- instance.setSpy(null);
+ if (mService != null) {
+ mService.setProxy(null);
+ mService.setSpy(null);
}
+ MediaRouter2ManagerTestActivity.finishActivity();
mUiAutomation.dropShellPermissionIdentity();
}
@@ -179,13 +207,10 @@
MediaRoute2Info routeToRemove = routes.get(ROUTE_ID2);
assertNotNull(routeToRemove);
- StubMediaRoute2ProviderService sInstance =
- StubMediaRoute2ProviderService.getInstance();
- assertNotNull(sInstance);
- sInstance.removeRoute(ROUTE_ID2);
+ mService.removeRoute(ROUTE_ID2);
assertTrue(removedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
- sInstance.addRoute(routeToRemove);
+ mService.addRoute(routeToRemove);
assertTrue(addedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
}
@@ -218,10 +243,7 @@
MediaRoute2Info routeToRemove = routes.get(ROUTE_ID2);
assertNotNull(routeToRemove);
- StubMediaRoute2ProviderService sInstance =
- StubMediaRoute2ProviderService.getInstance();
- assertNotNull(sInstance);
- sInstance.removeRoute(ROUTE_ID2);
+ mService.removeRoute(ROUTE_ID2);
// Wait until the route is removed.
assertTrue(removedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
@@ -230,7 +252,7 @@
assertNull(newRoutes.get(ROUTE_ID2));
// Revert the removal.
- sInstance.addRoute(routeToRemove);
+ mService.addRoute(routeToRemove);
assertTrue(addedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
mRouter2.unregisterRouteCallback(routeCallback);
}
@@ -445,9 +467,7 @@
CountDownLatch serviceOnReleaseSessionLatch = new CountDownLatch(1);
List<RoutingSessionInfo> sessions = new ArrayList<>();
- StubMediaRoute2ProviderService instance = StubMediaRoute2ProviderService.getInstance();
- assertNotNull(instance);
- instance.setSpy(new StubMediaRoute2ProviderService.Spy() {
+ mService.setSpy(new StubMediaRoute2ProviderService.Spy() {
@Override
public void onReleaseSession(long requestId, String sessionId) {
serviceOnReleaseSessionLatch.countDown();
@@ -652,12 +672,9 @@
Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(FEATURES_ALL);
MediaRoute2Info volRoute = routes.get(ROUTE_ID_VARIABLE_VOLUME);
- StubMediaRoute2ProviderService instance = StubMediaRoute2ProviderService.getInstance();
- assertNotNull(instance);
-
final List<Long> requestIds = new ArrayList<>();
final CountDownLatch onSetRouteVolumeLatch = new CountDownLatch(1);
- instance.setProxy(new StubMediaRoute2ProviderService.Proxy() {
+ mService.setProxy(new StubMediaRoute2ProviderService.Proxy() {
@Override
public void onSetRouteVolume(String routeId, int volume, long requestId) {
requestIds.add(requestId);
@@ -687,16 +704,16 @@
});
final long invalidRequestId = REQUEST_ID_NONE;
- instance.notifyRequestFailed(invalidRequestId, failureReason);
+ mService.notifyRequestFailed(invalidRequestId, failureReason);
assertFalse(onRequestFailedLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
final long validRequestId = requestIds.get(0);
- instance.notifyRequestFailed(validRequestId, failureReason);
+ mService.notifyRequestFailed(validRequestId, failureReason);
assertTrue(onRequestFailedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
// Test calling notifyRequestFailed() multiple times with the same valid requestId.
// onRequestFailed() shouldn't be called since the requestId has been already handled.
- instance.notifyRequestFailed(validRequestId, failureReason);
+ mService.notifyRequestFailed(validRequestId, failureReason);
assertFalse(onRequestFailedSecondCallLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
}
@@ -813,7 +830,8 @@
@Override
public void onRoutesAdded(List<MediaRoute2Info> routes) {
for (MediaRoute2Info route : routes) {
- if (!route.isSystemRoute()) {
+ if (!route.isSystemRoute()
+ && hasMatchingFeature(route.getFeatures(), routeFeatures)) {
addedLatch.countDown();
break;
}
@@ -834,10 +852,10 @@
mRouter2.registerRouteCallback(mExecutor, routeCallback,
new RouteDiscoveryPreference.Builder(routeFeatures, true).build());
try {
- if (mManager.getAllRoutes().isEmpty()) {
+ featuresLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS);
+ if (mManager.getAvailableRoutes(mPackageName).isEmpty()) {
addedLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS);
}
- featuresLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS);
return createRouteMap(mManager.getAvailableRoutes(mPackageName));
} finally {
mRouter2.unregisterRouteCallback(routeCallback);
@@ -845,6 +863,15 @@
}
}
+ boolean hasMatchingFeature(List<String> features1, List<String> features2) {
+ for (String feature : features1) {
+ if (features2.contains(feature)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
void awaitOnRouteChangedManager(Runnable task, String routeId,
Predicate<MediaRoute2Info> predicate) throws Exception {
CountDownLatch latch = new CountDownLatch(1);
diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTestActivity.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTestActivity.java
new file mode 100644
index 0000000..ac2a8bb
--- /dev/null
+++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTestActivity.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.mediaroutertest;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.WindowManager;
+
+import androidx.test.core.app.ActivityScenario;
+
+public class MediaRouter2ManagerTestActivity extends Activity {
+
+ private static ActivityScenario<MediaRouter2ManagerTestActivity> sActivityScenario;
+
+ public static ActivityScenario<MediaRouter2ManagerTestActivity> startActivity(Context context) {
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.setClass(context, MediaRouter2ManagerTestActivity.class);
+ sActivityScenario = ActivityScenario.launch(intent);
+ return sActivityScenario;
+ }
+
+ public static void finishActivity() {
+ if (sActivityScenario != null) {
+ // TODO: Sometimes calling this takes about 5 seconds. Need to figure out why.
+ sActivityScenario.close();
+ sActivityScenario = null;
+ }
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setTurnScreenOn(true);
+ setShowWhenLocked(true);
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+ }
+}
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-sv/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-sv/strings.xml
index 7314005..57e74e9 100644
--- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-sv/strings.xml
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-sv/strings.xml
@@ -18,7 +18,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="connectivityResourcesAppLabel" msgid="8294935652079168395">"Resurser för systemanslutning"</string>
- <string name="wifi_available_sign_in" msgid="5254156478006453593">"Logga in på ett Wi-Fi-nätverk"</string>
+ <string name="wifi_available_sign_in" msgid="5254156478006453593">"Logga in på ett wifi-nätverk"</string>
<string name="network_available_sign_in" msgid="7794369329839408792">"Logga in på nätverket"</string>
<!-- no translation found for network_available_sign_in_detailed (3643910593681893097) -->
<skip />
@@ -34,7 +34,7 @@
<string name="network_switch_metered_toast" msgid="8831325515040986641">"Byte av nätverk från <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> till <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
<string-array name="network_switch_type_name">
<item msgid="5454013645032700715">"mobildata"</item>
- <item msgid="6341719431034774569">"Wi-Fi"</item>
+ <item msgid="6341719431034774569">"Wifi"</item>
<item msgid="5081440868800877512">"Bluetooth"</item>
<item msgid="1160736166977503463">"Ethernet"</item>
<item msgid="7347618872551558605">"VPN"</item>
diff --git a/packages/PrintSpooler/res/values-my/strings.xml b/packages/PrintSpooler/res/values-my/strings.xml
index cb0b899..14ccbf8 100644
--- a/packages/PrintSpooler/res/values-my/strings.xml
+++ b/packages/PrintSpooler/res/values-my/strings.xml
@@ -27,7 +27,7 @@
<string name="label_duplex" msgid="5370037254347072243">"နှစ်ဖက်လှ"</string>
<string name="label_orientation" msgid="2853142581990496477">"အနေအထား"</string>
<string name="label_pages" msgid="7768589729282182230">"စာမျက်နှာများ"</string>
- <string name="destination_default_text" msgid="5422708056807065710">"ပုံနှိပ်စက်ကို ရွေးပါ"</string>
+ <string name="destination_default_text" msgid="5422708056807065710">"ပရင်တာကို ရွေးပါ"</string>
<string name="template_all_pages" msgid="3322235982020148762">"အားလုံး <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
<string name="template_page_range" msgid="428638530038286328">"<xliff:g id="PAGE_COUNT">%1$s</xliff:g>ဘောင် ထဲမှာ"</string>
<string name="pages_range_example" msgid="8558694453556945172">"ဥပမာ ၁-၅၊ ၈၊ ၁၁-၁၃"</string>
@@ -36,7 +36,7 @@
<string name="printing_app_crashed" msgid="854477616686566398">"စာထုတ်လုပ်သော အက်ပ်ခဏ ပျက်သွားပါသည်"</string>
<string name="generating_print_job" msgid="3119608742651698916">"စာထုတ်အလုပ်ကို လုပ်နေပါသည်"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"PDF အဖြစ်သိမ်းရန်"</string>
- <string name="all_printers" msgid="5018829726861876202">"စာထုတ်စက် အားလုံး"</string>
+ <string name="all_printers" msgid="5018829726861876202">"ပ အားလုံး"</string>
<string name="print_dialog" msgid="32628687461331979">"စာထုတ်ရန် အချက်ပြခြင်း"</string>
<string name="current_page_template" msgid="5145005201131935302">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g>/<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="page_description_template" msgid="6831239682256197161">"<xliff:g id="PAGE_COUNT">%2$d</xliff:g>ထဲက စာမျက်နှာ <xliff:g id="CURRENT_PAGE">%1$d</xliff:g>"</string>
@@ -48,16 +48,16 @@
<string name="print_options_expanded" msgid="6944679157471691859">"ပရင့်ထုတ် ရွေးစရာများကို ချဲ့ထား"</string>
<string name="print_options_collapsed" msgid="7455930445670414332">"ပရင့်ထုတ် ရွေးစရာများကို ခေါက်ထား"</string>
<string name="search" msgid="5421724265322228497">"ရှာဖွေခြင်း"</string>
- <string name="all_printers_label" msgid="3178848870161526399">"စာထုတ်စက် အားလုံး"</string>
+ <string name="all_printers_label" msgid="3178848870161526399">"ပ အားလုံး"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"ဝန်ဆောင်မှုထည့်ရန်"</string>
<string name="print_search_box_shown_utterance" msgid="7967404953901376090">"ရှာဖွေစရာ နေရာ မြင်တွေ့ရပါသည်"</string>
<string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"ရှာဖွေရန် နေရာ ပျောက်ကွယ်နေပါသည်"</string>
<string name="print_add_printer" msgid="1088656468360653455">"ပရင်တာထည့်ရန်"</string>
- <string name="print_select_printer" msgid="7388760939873368698">"စာထုတ်စက်ကို ရွေးရန်"</string>
- <string name="print_forget_printer" msgid="5035287497291910766">"စာထုတ်စက်ကို မေ့လိုက်ရန်"</string>
+ <string name="print_select_printer" msgid="7388760939873368698">"ပရင်တာကို ရွေးရန်"</string>
+ <string name="print_forget_printer" msgid="5035287497291910766">"ပရင်တာကို မေ့လိုက်ရန်"</string>
<plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
- <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> စာထုတ်စက်များ တွေ့ရှိပါသည်</item>
- <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g>စာထုတ်စက် တွေ့ရှိပါသည်</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> ပရင်တာများ တွေ့ရှိပါသည်</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g>ပရင်တာ တွေ့ရှိပါသည်</item>
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"ဤပရင်တာ အကြောင်း ပိုမိုလေ့လာပါ"</string>
@@ -67,25 +67,25 @@
<string name="print_services_disabled_toast" msgid="9089060734685174685">"အချို့ပုံနှိပ်ဝန်ဆောင်မှုများကို ပိတ်ထားပါသည်"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"ပရင်တာများကို ရှာနေသည်"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"ပုံနှိပ်ထုတ်ယူရေး ဝန်ဆောင်မှုများ ဖွင့်မထားပါ"</string>
- <string name="print_no_printers" msgid="4869403323900054866">"စာထုတ်စက် တစ်ခုမှ မတွေ့ရှိပါ"</string>
+ <string name="print_no_printers" msgid="4869403323900054866">"ပ တစ်ခုမှ မတွေ့ရှိပါ"</string>
<string name="cannot_add_printer" msgid="7840348733668023106">"ပုံနှိပ်စက်များကို ထည့်၍မရပါ"</string>
- <string name="select_to_add_printers" msgid="3800709038689830974">"ပုံနှိပ်စက်ထည့်ရန် ရွေးပါ"</string>
+ <string name="select_to_add_printers" msgid="3800709038689830974">"ပရင်တာထည့်ရန် ရွေးပါ"</string>
<string name="enable_print_service" msgid="3482815747043533842">"ဖွင့်ရန် ရွေးပါ"</string>
<string name="enabled_services_title" msgid="7036986099096582296">"ဖွင့်ထားသည့် ဝန်ဆောင်မှုများ"</string>
<string name="recommended_services_title" msgid="3799434882937956924">"အကြံပြုထားသည့် ဝန်ဆောင်မှုများ"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"ပိတ်ထားသည့် ဝန်ဆောင်မှုများ"</string>
<string name="all_services_title" msgid="5578662754874906455">"ဝန်ဆောင်မှုများ အားလုံး"</string>
<plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
- <item quantity="other">ပုံနှိပ်စက် <xliff:g id="COUNT_1">%1$s</xliff:g> ခုကို ရှာဖွေရန် စနစ်ထည့်သွင်းပါ</item>
- <item quantity="one">ပုံနှိပ်စက် <xliff:g id="COUNT_0">%1$s</xliff:g> ခုကို ရှာဖွေရန် စနစ်ထည့်သွင်းပါ</item>
+ <item quantity="other">ပရင်တာ <xliff:g id="COUNT_1">%1$s</xliff:g> ခုကို ရှာဖွေရန် စနစ်ထည့်သွင်းပါ</item>
+ <item quantity="one">ပရင်တာ <xliff:g id="COUNT_0">%1$s</xliff:g> ခုကို ရှာဖွေရန် စနစ်ထည့်သွင်းပါ</item>
</plurals>
<string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> ကို စာထုတ်နေပါသည်"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> ကို ပယ်ဖျက်နေပါသည်"</string>
- <string name="failed_notification_title_template" msgid="2256217208186530973">"စာထုတ်စက်မှ အမှား <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <string name="blocked_notification_title_template" msgid="1175435827331588646">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>ကိုစာထုတ်စက်ကငြင်းလိုက်သည်"</string>
+ <string name="failed_notification_title_template" msgid="2256217208186530973">"ပရင်တာမှ အမှား <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
+ <string name="blocked_notification_title_template" msgid="1175435827331588646">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> ကိုပရင်တာက ငြင်းလိုက်သည်"</string>
<string name="cancel" msgid="4373674107267141885">"မလုပ်တော့"</string>
<string name="restart" msgid="2472034227037808749">"ပြန်စရန်"</string>
- <string name="no_connection_to_printer" msgid="2159246915977282728">"စာထုတ်စက်နဲ့ ဆက်သွယ်ထားမှု မရှိပါ"</string>
+ <string name="no_connection_to_printer" msgid="2159246915977282728">"ပရင်တာနှင့် ဆက်သွယ်ထားမှု မရှိပါ"</string>
<string name="reason_unknown" msgid="5507940196503246139">"မသိ"</string>
<string name="print_service_security_warning_title" msgid="2160752291246775320">"<xliff:g id="SERVICE">%1$s</xliff:g> ကိုသုံးမလား။"</string>
<string name="print_service_security_warning_summary" msgid="1427434625361692006">"သင်၏ စာရွက်စာတမ်းများသည် ပရင်တာထံသို့ သွားစဉ် ဆာဗာ တစ်ခု သို့မဟုတ် ပိုများပြီး ဖြတ်ကျော်နိုင်ရသည်။"</string>
@@ -105,7 +105,7 @@
<string name="print_write_error_message" msgid="5787642615179572543">"ဖိုင်သို့ မရေးနိုင်ခဲ့"</string>
<string name="print_error_default_message" msgid="8602678405502922346">"လုပ်၍မရခဲ့ပါ။ ထပ်စမ်းကြည့်ပါ။"</string>
<string name="print_error_retry" msgid="1426421728784259538">"ထပ်စမ်းကြည့်ရန်"</string>
- <string name="print_error_printer_unavailable" msgid="8985614415253203381">"ဒီပရင်တာမှာ ယခုအချိန်မှာ မရနိုင်ပါ။"</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"ဤပရင်တာသည် ယခုအချိန်တွင် မရနိုင်ပါ။"</string>
<string name="print_cannot_load_page" msgid="6179560924492912009">"အစမ်းကြည့်ခြင်းကို ပြသ၍မရပါ"</string>
<string name="print_preparing_preview" msgid="3939930735671364712">"အစမ်းကြည့်ရန် ပြင်ဆင်နေ…"</string>
</resources>
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt
index 6d6bc07..20273d0 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt
@@ -8,6 +8,7 @@
import android.content.Context
import android.graphics.Matrix
import android.graphics.Rect
+import android.os.Looper
import android.os.RemoteException
import android.util.MathUtils
import android.view.IRemoteAnimationFinishedCallback
@@ -73,16 +74,20 @@
* in [Controller.onLaunchAnimationProgress]. No animation will start if there is no window
* opening.
*
- * If [controller] is null, then the intent will be started and no animation will run.
+ * If [controller] is null or [animate] is false, then the intent will be started and no
+ * animation will run.
*
* This method will throw any exception thrown by [intentStarter].
*/
+ @JvmOverloads
inline fun startIntentWithAnimation(
controller: Controller?,
+ animate: Boolean = true,
intentStarter: (RemoteAnimationAdapter?) -> Int
) {
- if (controller == null) {
+ if (controller == null || !animate) {
intentStarter(null)
+ controller?.callOnIntentStartedOnMainThread(willAnimate = false)
return
}
@@ -95,7 +100,7 @@
val launchResult = intentStarter(animationAdapter)
val willAnimate = launchResult == ActivityManager.START_TASK_TO_FRONT ||
launchResult == ActivityManager.START_SUCCESS
- runner.context.mainExecutor.execute { controller.onIntentStarted(willAnimate) }
+ controller.callOnIntentStartedOnMainThread(willAnimate)
// If we expect an animation, post a timeout to cancel it in case the remote animation is
// never started.
@@ -104,17 +109,30 @@
}
}
+ @PublishedApi
+ internal fun Controller.callOnIntentStartedOnMainThread(willAnimate: Boolean) {
+ if (Looper.myLooper() != Looper.getMainLooper()) {
+ this.getRootView().context.mainExecutor.execute {
+ this.onIntentStarted(willAnimate)
+ }
+ } else {
+ this.onIntentStarted(willAnimate)
+ }
+ }
+
/**
* Same as [startIntentWithAnimation] but allows [intentStarter] to throw a
* [PendingIntent.CanceledException] which must then be handled by the caller. This is useful
* for Java caller starting a [PendingIntent].
*/
@Throws(PendingIntent.CanceledException::class)
+ @JvmOverloads
fun startPendingIntentWithAnimation(
controller: Controller?,
+ animate: Boolean = true,
intentStarter: PendingIntentStarter
) {
- startIntentWithAnimation(controller) { intentStarter.startPendingIntent(it) }
+ startIntentWithAnimation(controller, animate) { intentStarter.startPendingIntent(it) }
}
/** Create a new animation [Runner] controlled by [controller]. */
diff --git a/packages/SystemUI/res/drawable/qs_background_primary.xml b/packages/SystemUI/res/drawable/qs_background_primary.xml
deleted file mode 100644
index 30d026e..0000000
--- a/packages/SystemUI/res/drawable/qs_background_primary.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2021 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-<inset xmlns:android="http://schemas.android.com/apk/res/android">
- <shape>
- <solid android:color="?attr/underSurfaceColor"/>
- <corners android:radius="@dimen/notification_corner_radius" />
- </shape>
-</inset>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/global_actions_grid_item_lite.xml b/packages/SystemUI/res/layout/global_actions_grid_item_lite.xml
index 9ab1ac8..e1ee06d 100644
--- a/packages/SystemUI/res/layout/global_actions_grid_item_lite.xml
+++ b/packages/SystemUI/res/layout/global_actions_grid_item_lite.xml
@@ -35,13 +35,11 @@
android:id="@*android:id/message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:ellipsize="end"
+ android:ellipsize="marquee"
android:marqueeRepeatLimit="marquee_forever"
- android:maxLines="2"
- android:textSize="12sp"
+ android:singleLine="true"
+ android:textSize="14sp"
android:gravity="center"
android:textColor="@color/global_actions_lite_text"
- android:breakStrategy="high_quality"
- android:hyphenationFrequency="full"
android:textAppearance="?android:attr/textAppearanceSmall" />
</com.android.systemui.globalactions.GlobalActionsItem>
diff --git a/packages/SystemUI/res/layout/media_smartspace_recommendations.xml b/packages/SystemUI/res/layout/media_smartspace_recommendations.xml
index 9210d05..1c4c89f 100644
--- a/packages/SystemUI/res/layout/media_smartspace_recommendations.xml
+++ b/packages/SystemUI/res/layout/media_smartspace_recommendations.xml
@@ -19,29 +19,57 @@
<com.android.systemui.util.animation.TransitionLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
android:id="@+id/media_recommendations"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:paddingTop="8dp"
- android:paddingBottom="8dp"
+ android:paddingStart="@dimen/qs_media_padding"
+ android:paddingEnd="@dimen/qs_media_padding"
android:clipChildren="false"
android:clipToPadding="false"
android:forceHasOverlappingRendering="false"
android:background="@drawable/qs_media_background">
+ <androidx.constraintlayout.widget.Guideline
+ android:id="@+id/media_vertical_start_guideline"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ app:layout_constraintGuide_percent="0.25" />
+
+ <ImageView
+ android:id="@+id/recommendation_card_icon"
+ android:layout_width="@dimen/qs_aa_media_rec_header_icon_size"
+ android:layout_height="@dimen/qs_aa_media_rec_header_icon_size"
+ android:src="@drawable/ic_headset"
+ android:tint="?android:attr/colorPrimary" />
+
+ <TextView
+ android:id="@+id/recommendation_card_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:text="@string/controls_media_smartspace_rec_title"
+ android:fontFamily="google-sans-medium"
+ android:textColor="?android:attr/colorPrimary"
+ android:textDirection="locale"
+ android:textSize="@dimen/qq_aa_media_rec_header_text_size" />
+
<ImageView
android:id="@+id/media_cover1"
android:layout_width="@dimen/qs_aa_media_rec_album_size"
android:layout_height="@dimen/qs_aa_media_rec_album_size"
android:adjustViewBounds="true"
android:background="@drawable/bg_smartspace_media_item"
+ android:backgroundTint="?androidprv:attr/colorAccentSecondary"
android:clipToOutline="true"
android:scaleType="centerCrop"/>
- <ImageView
+ <com.android.internal.widget.CachingIconView
android:id="@+id/media_logo1"
- android:layout_width="@dimen/qs_aa_media_rec_icon_size"
- android:layout_height="@dimen/qs_aa_media_rec_icon_size" />
+ android:layout_width="@dimen/qs_media_icon_size"
+ android:layout_height="@dimen/qs_media_icon_size"
+ android:background="@drawable/qs_media_icon_background" />
<ImageView
android:id="@+id/media_cover2"
@@ -49,13 +77,15 @@
android:layout_height="@dimen/qs_aa_media_rec_album_size"
android:adjustViewBounds="true"
android:background="@drawable/bg_smartspace_media_item"
+ android:backgroundTint="?androidprv:attr/colorAccentSecondary"
android:clipToOutline="true"
android:scaleType="centerCrop"/>
- <ImageView
+ <com.android.internal.widget.CachingIconView
android:id="@+id/media_logo2"
- android:layout_width="@dimen/qs_aa_media_rec_icon_size"
- android:layout_height="@dimen/qs_aa_media_rec_icon_size" />
+ android:layout_width="@dimen/qs_media_icon_size"
+ android:layout_height="@dimen/qs_media_icon_size"
+ android:background="@drawable/qs_media_icon_background" />
<ImageView
android:id="@+id/media_cover3"
@@ -63,13 +93,15 @@
android:layout_height="@dimen/qs_aa_media_rec_album_size"
android:adjustViewBounds="true"
android:background="@drawable/bg_smartspace_media_item"
+ android:backgroundTint="?androidprv:attr/colorAccentSecondary"
android:clipToOutline="true"
android:scaleType="centerCrop"/>
- <ImageView
+ <com.android.internal.widget.CachingIconView
android:id="@+id/media_logo3"
- android:layout_width="@dimen/qs_aa_media_rec_icon_size"
- android:layout_height="@dimen/qs_aa_media_rec_icon_size" />
+ android:layout_width="@dimen/qs_media_icon_size"
+ android:layout_height="@dimen/qs_media_icon_size"
+ android:background="@drawable/qs_media_icon_background" />
<ImageView
android:id="@+id/media_cover4"
@@ -77,15 +109,49 @@
android:layout_height="@dimen/qs_aa_media_rec_album_size"
android:adjustViewBounds="true"
android:background="@drawable/bg_smartspace_media_item"
+ android:backgroundTint="?androidprv:attr/colorAccentSecondary"
android:clipToOutline="true"
android:scaleType="centerCrop"/>
- <ImageView
+ <com.android.internal.widget.CachingIconView
android:id="@+id/media_logo4"
- android:layout_width="@dimen/qs_aa_media_rec_icon_size"
- android:layout_height="@dimen/qs_aa_media_rec_icon_size" />
+ android:layout_width="@dimen/qs_media_icon_size"
+ android:layout_height="@dimen/qs_media_icon_size"
+ android:background="@drawable/qs_media_icon_background" />
- <!-- Constraints are set here as they are the same regardless of host -->
+ <ImageView
+ android:id="@+id/media_cover5"
+ android:layout_width="@dimen/qs_aa_media_rec_album_size"
+ android:layout_height="@dimen/qs_aa_media_rec_album_size"
+ android:adjustViewBounds="true"
+ android:background="@drawable/bg_smartspace_media_item"
+ android:backgroundTint="?androidprv:attr/colorAccentSecondary"
+ android:clipToOutline="true"
+ android:scaleType="centerCrop"/>
+
+ <com.android.internal.widget.CachingIconView
+ android:id="@+id/media_logo5"
+ android:layout_width="@dimen/qs_media_icon_size"
+ android:layout_height="@dimen/qs_media_icon_size"
+ android:background="@drawable/qs_media_icon_background" />
+
+ <ImageView
+ android:id="@+id/media_cover6"
+ android:layout_width="@dimen/qs_aa_media_rec_album_size"
+ android:layout_height="@dimen/qs_aa_media_rec_album_size"
+ android:adjustViewBounds="true"
+ android:background="@drawable/bg_smartspace_media_item"
+ android:backgroundTint="?androidprv:attr/colorAccentSecondary"
+ android:clipToOutline="true"
+ android:scaleType="centerCrop"/>
+
+ <com.android.internal.widget.CachingIconView
+ android:id="@+id/media_logo6"
+ android:layout_width="@dimen/qs_media_icon_size"
+ android:layout_height="@dimen/qs_media_icon_size"
+ android:background="@drawable/qs_media_icon_background" />
+
+ <!-- Long press menu -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -136,7 +202,8 @@
android:minWidth="48dp"
android:minHeight="48dp"
app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintEnd_toStartOf="@id/dismiss" >
+ app:layout_constraintEnd_toStartOf="@id/dismiss"
+ app:layout_constraintTop_toBottomOf="@id/remove_text">
<TextView
android:layout_gravity="bottom"
@@ -158,7 +225,8 @@
android:minWidth="48dp"
android:minHeight="48dp"
app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintEnd_toEndOf="parent">
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintTop_toBottomOf="@id/remove_text">
<TextView
android:layout_gravity="bottom"
diff --git a/packages/SystemUI/res/layout/ongoing_privacy_chip.xml b/packages/SystemUI/res/layout/ongoing_privacy_chip.xml
index bad5826..676e492 100644
--- a/packages/SystemUI/res/layout/ongoing_privacy_chip.xml
+++ b/packages/SystemUI/res/layout/ongoing_privacy_chip.xml
@@ -22,14 +22,16 @@
android:layout_height="match_parent"
android:layout_width="wrap_content"
android:layout_gravity="center_vertical|end"
- android:focusable="true"
- android:minWidth="48dp" >
+ android:focusable="true" >
<LinearLayout
android:id="@+id/icons_container"
android:layout_height="@dimen/ongoing_appops_chip_height"
android:layout_width="wrap_content"
- android:gravity="center_vertical"
+ android:paddingStart="10dp"
+ android:paddingEnd="10dp"
+ android:gravity="center"
android:layout_gravity="center"
+ android:minWidth="56dp"
/>
</com.android.systemui.privacy.OngoingPrivacyChip>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/qs_panel.xml b/packages/SystemUI/res/layout/qs_panel.xml
index 2cafd1b..7cf3d01 100644
--- a/packages/SystemUI/res/layout/qs_panel.xml
+++ b/packages/SystemUI/res/layout/qs_panel.xml
@@ -21,13 +21,6 @@
android:clipToPadding="false"
android:clipChildren="false" >
- <!-- Main QS background -->
- <View
- android:id="@+id/quick_settings_background"
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:background="@drawable/qs_background_primary" />
-
<com.android.systemui.qs.NonInterceptingScrollView
android:id="@+id/expanded_qs_scroll_view"
android:layout_width="match_parent"
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index bf13c21..ee25a10 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -280,8 +280,7 @@
<color name="screenrecord_status_color">#E94235</color>
- <!-- TODO(b/178093014) Colors for privacy dialog. These should be changed to the new palette -->
- <color name="privacy_circle">#1E8E3E</color> <!-- g600 -->
+ <color name="privacy_circle">#5BB974</color> <!-- g400 -->
<!-- Accessibility floating menu -->
<color name="accessibility_floating_menu_background">#CCFFFFFF</color> <!-- 80% -->
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index b76a4ce..5371b41 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1237,7 +1237,7 @@
<!-- Icon size of Ongoing App Ops chip -->
<dimen name="ongoing_appops_chip_icon_size">16dp</dimen>
<!-- Radius of Ongoing App Ops chip corners -->
- <dimen name="ongoing_appops_chip_bg_corner_radius">16dp</dimen>
+ <dimen name="ongoing_appops_chip_bg_corner_radius">28dp</dimen>
<dimen name="ongoing_appops_dialog_side_margins">@dimen/notification_shade_content_margin_horizontal</dimen>
@@ -1276,8 +1276,10 @@
<dimen name="qs_media_disabled_seekbar_vertical_padding">36dp</dimen>
<!-- Size of Smartspace media recommendations cards in the QSPanel carousel -->
- <dimen name="qs_aa_media_rec_album_size">80dp</dimen>
- <dimen name="qs_aa_media_rec_icon_size">20dp</dimen>
+ <dimen name="qs_aa_media_rec_header_icon_padding">10dp</dimen>
+ <dimen name="qs_aa_media_rec_header_icon_size">18dp</dimen>
+ <dimen name="qs_aa_media_rec_album_size">72dp</dimen>
+ <dimen name="qq_aa_media_rec_header_text_size">16sp</dimen>
<!-- Window magnification -->
<dimen name="magnification_border_drag_size">35dp</dimen>
diff --git a/packages/SystemUI/res/values/flags.xml b/packages/SystemUI/res/values/flags.xml
index f4d4ab8..6104588 100644
--- a/packages/SystemUI/res/values/flags.xml
+++ b/packages/SystemUI/res/values/flags.xml
@@ -22,7 +22,6 @@
<bool name="flag_notification_pipeline2_rendering">false</bool>
<bool name="flag_notif_updates">true</bool>
- <bool name="flag_shade_is_opaque">true</bool>
<bool name="flag_monet">false</bool>
<!-- b/171917882 -->
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index bbb5519..673a03d 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -2729,6 +2729,8 @@
<string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half">Move to edge and hide</string>
<!-- Action in accessibility menu to move the accessibility floating button out the edge and show. [CHAR LIMIT=36]-->
<string name="accessibility_floating_button_action_move_out_edge_and_show">Move out edge and show</string>
+ <!-- Action in accessibility menu to toggle on/off the accessibility feature. [CHAR LIMIT=30]-->
+ <string name="accessibility_floating_button_action_double_tap_to_toggle">toggle</string>
<!-- Device Controls strings -->
<!-- Device Controls empty state, title [CHAR LIMIT=30] -->
@@ -2837,6 +2839,9 @@
<!-- Label for button to go to media control settings screen [CHAR_LIMIT=30] -->
<string name="controls_media_settings_button">Settings</string>
+ <!-- Title for Smartspace recommendation card within media controls [CHAR_LIMIT=50] -->
+ <string name="controls_media_smartspace_rec_title">Play</string>
+
<!-- Error message indicating that a control timed out while waiting for an update [CHAR_LIMIT=30] -->
<string name="controls_error_timeout">Inactive, check app</string>
<!-- Error message indicating that an unspecified error occurred while getting the status, and
diff --git a/packages/SystemUI/res/xml/media_recommendation.xml b/packages/SystemUI/res/xml/media_recommendation.xml
deleted file mode 100644
index a1bd231..0000000
--- a/packages/SystemUI/res/xml/media_recommendation.xml
+++ /dev/null
@@ -1,97 +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
- -->
-<ConstraintSet
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto">
-
- <Constraint
- android:id="@+id/media_cover1"
- android:layout_width="@dimen/qs_aa_media_rec_album_size"
- android:layout_height="@dimen/qs_aa_media_rec_album_size"
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintEnd_toStartOf="@id/media_cover2"
- app:layout_constraintHorizontal_weight="1"
- android:visibility="gone"/>
-
- <Constraint
- android:id="@+id/media_logo1"
- android:layout_width="@dimen/qs_aa_media_rec_icon_size"
- android:layout_height="@dimen/qs_aa_media_rec_icon_size"
- app:layout_constraintEnd_toEndOf="@+id/media_cover1"
- app:layout_constraintBottom_toBottomOf="@+id/media_cover1"
- android:visibility="gone" />
-
- <Constraint
- android:id="@+id/media_cover2"
- android:layout_width="@dimen/qs_aa_media_rec_album_size"
- android:layout_height="@dimen/qs_aa_media_rec_album_size"
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintStart_toEndOf="@id/media_cover1"
- app:layout_constraintEnd_toStartOf="@id/media_cover3"
- app:layout_constraintHorizontal_weight="1"
- android:visibility="gone"/>
-
- <Constraint
- android:id="@+id/media_logo2"
- android:layout_width="@dimen/qs_aa_media_rec_icon_size"
- android:layout_height="@dimen/qs_aa_media_rec_icon_size"
- app:layout_constraintEnd_toEndOf="@+id/media_cover2"
- app:layout_constraintBottom_toBottomOf="@+id/media_cover2"
- android:visibility="gone" />
-
- <Constraint
- android:id="@+id/media_cover3"
- android:layout_width="@dimen/qs_aa_media_rec_album_size"
- android:layout_height="@dimen/qs_aa_media_rec_album_size"
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintStart_toEndOf="@id/media_cover2"
- app:layout_constraintEnd_toStartOf="@id/media_cover4"
- app:layout_constraintHorizontal_weight="1"
- android:visibility="gone"/>
-
- <Constraint
- android:id="@+id/media_logo3"
- android:layout_width="@dimen/qs_aa_media_rec_icon_size"
- android:layout_height="@dimen/qs_aa_media_rec_icon_size"
- app:layout_constraintEnd_toEndOf="@+id/media_cover3"
- app:layout_constraintBottom_toBottomOf="@+id/media_cover3"
- android:visibility="gone" />
-
- <Constraint
- android:id="@+id/media_cover4"
- android:layout_width="@dimen/qs_aa_media_rec_album_size"
- android:layout_height="@dimen/qs_aa_media_rec_album_size"
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintStart_toEndOf="@id/media_cover3"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintHorizontal_weight="1"
- android:visibility="gone"/>
-
- <Constraint
- android:id="@+id/media_logo4"
- android:layout_width="@dimen/qs_aa_media_rec_icon_size"
- android:layout_height="@dimen/qs_aa_media_rec_icon_size"
- app:layout_constraintEnd_toEndOf="@+id/media_cover4"
- app:layout_constraintBottom_toBottomOf="@+id/media_cover4"
- android:visibility="gone" />
-
-</ConstraintSet>
diff --git a/packages/SystemUI/res/xml/media_recommendation_collapsed.xml b/packages/SystemUI/res/xml/media_recommendation_collapsed.xml
new file mode 100644
index 0000000..afd800b
--- /dev/null
+++ b/packages/SystemUI/res/xml/media_recommendation_collapsed.xml
@@ -0,0 +1,172 @@
+<?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
+ -->
+<ConstraintSet
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto">
+
+ <Constraint
+ android:id="@+id/recommendation_card_icon"
+ android:layout_width="@dimen/qs_aa_media_rec_header_icon_size"
+ android:layout_height="@dimen/qs_aa_media_rec_header_icon_size"
+ android:layout_marginTop="@dimen/qs_aa_media_rec_header_icon_padding"
+ android:layout_marginStart="@dimen/qs_aa_media_rec_header_icon_padding"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toStartOf="@id/media_vertical_start_guideline"
+ app:layout_constraintHorizontal_bias="0" />
+
+ <Constraint
+ android:id="@+id/recommendation_card_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="@dimen/qs_aa_media_rec_header_icon_padding"
+ app:layout_constraintTop_toBottomOf="@id/recommendation_card_icon"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toStartOf="@id/media_vertical_start_guideline"
+ app:layout_constraintHorizontal_bias="0" />
+
+ <Constraint
+ android:id="@+id/media_cover1"
+ android:layout_width="@dimen/qs_aa_media_rec_album_size"
+ android:layout_height="@dimen/qs_aa_media_rec_album_size"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toEndOf="@id/media_vertical_start_guideline"
+ app:layout_constraintEnd_toStartOf="@id/media_cover2"
+ app:layout_constraintHorizontal_chainStyle="spread"
+ android:visibility="gone" />
+
+ <Constraint
+ android:id="@+id/media_logo1"
+ android:layout_width="@dimen/qs_media_icon_size"
+ android:layout_height="@dimen/qs_media_icon_size"
+ android:translationY="@dimen/qs_media_icon_offset"
+ android:translationX="@dimen/qs_media_icon_offset"
+ app:layout_constraintEnd_toEndOf="@+id/media_cover1"
+ app:layout_constraintBottom_toBottomOf="@+id/media_cover1"
+ android:visibility="gone" />
+
+ <Constraint
+ android:id="@+id/media_cover2"
+ android:layout_width="@dimen/qs_aa_media_rec_album_size"
+ android:layout_height="@dimen/qs_aa_media_rec_album_size"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toEndOf="@id/media_cover1"
+ app:layout_constraintEnd_toStartOf="@id/media_cover3"
+ app:layout_constraintHorizontal_chainStyle="spread"
+ android:visibility="gone" />
+
+ <Constraint
+ android:id="@+id/media_logo2"
+ android:layout_width="@dimen/qs_media_icon_size"
+ android:layout_height="@dimen/qs_media_icon_size"
+ android:translationY="@dimen/qs_media_icon_offset"
+ android:translationX="@dimen/qs_media_icon_offset"
+ app:layout_constraintEnd_toEndOf="@+id/media_cover2"
+ app:layout_constraintBottom_toBottomOf="@+id/media_cover2"
+ android:visibility="gone" />
+
+ <Constraint
+ android:id="@+id/media_cover3"
+ android:layout_width="@dimen/qs_aa_media_rec_album_size"
+ android:layout_height="@dimen/qs_aa_media_rec_album_size"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toEndOf="@id/media_cover2"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintHorizontal_chainStyle="spread"
+ app:layout_constraintHorizontal_bias="1"
+ android:visibility="gone" />
+
+ <Constraint
+ android:id="@+id/media_logo3"
+ android:layout_width="@dimen/qs_media_icon_size"
+ android:layout_height="@dimen/qs_media_icon_size"
+ android:translationY="@dimen/qs_media_icon_offset"
+ android:translationX="@dimen/qs_media_icon_offset"
+ app:layout_constraintEnd_toEndOf="@+id/media_cover3"
+ app:layout_constraintBottom_toBottomOf="@+id/media_cover3"
+ android:visibility="gone" />
+
+ <Constraint
+ android:id="@+id/media_cover4"
+ android:layout_width="@dimen/qs_aa_media_rec_album_size"
+ android:layout_height="0dp"
+ app:layout_constraintTop_toBottomOf="@+id/media_cover1"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toEndOf="@id/media_vertical_start_guideline"
+ app:layout_constraintEnd_toStartOf="@id/media_cover5"
+ app:layout_constraintHorizontal_chainStyle="spread"
+ app:layout_constraintHorizontal_bias="1"
+ android:visibility="gone" />
+
+ <Constraint
+ android:id="@+id/media_logo4"
+ android:layout_width="@dimen/qs_media_icon_size"
+ android:layout_height="0dp"
+ android:translationY="@dimen/qs_media_icon_offset"
+ android:translationX="@dimen/qs_media_icon_offset"
+ app:layout_constraintEnd_toEndOf="@+id/media_cover4"
+ app:layout_constraintBottom_toBottomOf="@+id/media_cover4"
+ android:visibility="gone" />
+
+ <Constraint
+ android:id="@+id/media_cover5"
+ android:layout_width="@dimen/qs_aa_media_rec_album_size"
+ android:layout_height="0dp"
+ app:layout_constraintTop_toBottomOf="@+id/media_cover2"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toEndOf="@+id/media_cover4"
+ app:layout_constraintEnd_toStartOf="@+id/media_cover6"
+ app:layout_constraintHorizontal_chainStyle="spread"
+ app:layout_constraintHorizontal_bias="1"
+ android:visibility="gone" />
+
+ <Constraint
+ android:id="@+id/media_logo5"
+ android:layout_width="@dimen/qs_media_icon_size"
+ android:layout_height="0dp"
+ android:translationY="@dimen/qs_media_icon_offset"
+ android:translationX="@dimen/qs_media_icon_offset"
+ app:layout_constraintEnd_toEndOf="@+id/media_cover5"
+ app:layout_constraintBottom_toBottomOf="@+id/media_cover5"
+ android:visibility="gone" />
+
+ <Constraint
+ android:id="@+id/media_cover6"
+ android:layout_width="@dimen/qs_aa_media_rec_album_size"
+ android:layout_height="0dp"
+ app:layout_constraintTop_toBottomOf="@id/media_cover3"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toEndOf="@id/media_cover5"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintHorizontal_chainStyle="spread"
+ app:layout_constraintHorizontal_bias="1"
+ android:visibility="gone" />
+
+ <Constraint
+ android:id="@+id/media_logo6"
+ android:layout_width="@dimen/qs_media_icon_size"
+ android:layout_height="0dp"
+ android:translationY="@dimen/qs_media_icon_offset"
+ android:translationX="@dimen/qs_media_icon_offset"
+ app:layout_constraintEnd_toEndOf="@+id/media_cover6"
+ app:layout_constraintBottom_toBottomOf="@+id/media_cover6"
+ android:visibility="gone" />
+
+</ConstraintSet>
diff --git a/packages/SystemUI/res/xml/media_recommendation_expanded.xml b/packages/SystemUI/res/xml/media_recommendation_expanded.xml
new file mode 100644
index 0000000..04a4877
--- /dev/null
+++ b/packages/SystemUI/res/xml/media_recommendation_expanded.xml
@@ -0,0 +1,181 @@
+<?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
+ -->
+<ConstraintSet
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto">
+
+ <Constraint
+ android:id="@+id/recommendation_card_icon"
+ android:layout_width="@dimen/qs_aa_media_rec_header_icon_size"
+ android:layout_height="@dimen/qs_aa_media_rec_header_icon_size"
+ android:layout_marginTop="@dimen/qs_media_padding"
+ android:layout_marginStart="@dimen/qs_aa_media_rec_header_icon_padding"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toStartOf="@id/media_vertical_start_guideline"
+ app:layout_constraintHorizontal_bias="0" />
+
+ <Constraint
+ android:id="@+id/recommendation_card_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="@dimen/qs_aa_media_rec_header_icon_padding"
+ app:layout_constraintTop_toBottomOf="@id/recommendation_card_icon"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toStartOf="@id/media_vertical_start_guideline"
+ app:layout_constraintHorizontal_bias="0" />
+
+ <Constraint
+ android:id="@+id/media_cover1"
+ android:layout_width="@dimen/qs_aa_media_rec_album_size"
+ android:layout_height="@dimen/qs_aa_media_rec_album_size"
+ android:layout_marginTop="@dimen/qs_media_padding"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toTopOf="@+id/media_cover4"
+ app:layout_constraintStart_toEndOf="@id/media_vertical_start_guideline"
+ app:layout_constraintEnd_toStartOf="@id/media_cover2"
+ app:layout_constraintHorizontal_chainStyle="spread"
+ android:visibility="gone" />
+
+ <Constraint
+ android:id="@+id/media_logo1"
+ android:layout_width="@dimen/qs_media_icon_size"
+ android:layout_height="@dimen/qs_media_icon_size"
+ android:translationY="@dimen/qs_media_icon_offset"
+ android:translationX="@dimen/qs_media_icon_offset"
+ app:layout_constraintEnd_toEndOf="@+id/media_cover1"
+ app:layout_constraintBottom_toBottomOf="@+id/media_cover1"
+ android:visibility="gone" />
+
+ <Constraint
+ android:id="@+id/media_cover2"
+ android:layout_width="@dimen/qs_aa_media_rec_album_size"
+ android:layout_height="@dimen/qs_aa_media_rec_album_size"
+ android:layout_marginTop="@dimen/qs_media_padding"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toTopOf="@+id/media_cover5"
+ app:layout_constraintStart_toEndOf="@id/media_cover1"
+ app:layout_constraintEnd_toStartOf="@id/media_cover3"
+ app:layout_constraintHorizontal_chainStyle="spread"
+ android:visibility="gone" />
+
+ <Constraint
+ android:id="@+id/media_logo2"
+ android:layout_width="@dimen/qs_media_icon_size"
+ android:layout_height="@dimen/qs_media_icon_size"
+ android:translationY="@dimen/qs_media_icon_offset"
+ android:translationX="@dimen/qs_media_icon_offset"
+ app:layout_constraintEnd_toEndOf="@+id/media_cover2"
+ app:layout_constraintBottom_toBottomOf="@+id/media_cover2"
+ android:visibility="gone" />
+
+ <Constraint
+ android:id="@+id/media_cover3"
+ android:layout_width="@dimen/qs_aa_media_rec_album_size"
+ android:layout_height="@dimen/qs_aa_media_rec_album_size"
+ android:layout_marginTop="@dimen/qs_media_padding"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toTopOf="@+id/media_cover6"
+ app:layout_constraintStart_toEndOf="@id/media_cover2"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintHorizontal_chainStyle="spread"
+ app:layout_constraintHorizontal_bias="1"
+ android:visibility="gone" />
+
+ <Constraint
+ android:id="@+id/media_logo3"
+ android:layout_width="@dimen/qs_media_icon_size"
+ android:layout_height="@dimen/qs_media_icon_size"
+ android:translationY="@dimen/qs_media_icon_offset"
+ android:translationX="@dimen/qs_media_icon_offset"
+ app:layout_constraintEnd_toEndOf="@+id/media_cover3"
+ app:layout_constraintBottom_toBottomOf="@+id/media_cover3"
+ android:visibility="gone" />
+
+ <Constraint
+ android:id="@+id/media_cover4"
+ android:layout_width="@dimen/qs_aa_media_rec_album_size"
+ android:layout_height="@dimen/qs_aa_media_rec_album_size"
+ android:layout_marginTop="@dimen/qs_media_padding"
+ android:layout_marginBottom="@dimen/qs_media_padding"
+ app:layout_constraintTop_toBottomOf="@+id/media_cover1"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toEndOf="@id/media_vertical_start_guideline"
+ app:layout_constraintEnd_toStartOf="@id/media_cover5"
+ app:layout_constraintHorizontal_chainStyle="spread"
+ app:layout_constraintHorizontal_bias="1"
+ android:visibility="gone" />
+
+ <Constraint
+ android:id="@+id/media_logo4"
+ android:layout_width="@dimen/qs_media_icon_size"
+ android:layout_height="@dimen/qs_media_icon_size"
+ android:translationY="@dimen/qs_media_icon_offset"
+ android:translationX="@dimen/qs_media_icon_offset"
+ app:layout_constraintEnd_toEndOf="@+id/media_cover4"
+ app:layout_constraintBottom_toBottomOf="@+id/media_cover4"
+ android:visibility="gone" />
+
+ <Constraint
+ android:id="@+id/media_cover5"
+ android:layout_width="@dimen/qs_aa_media_rec_album_size"
+ android:layout_height="@dimen/qs_aa_media_rec_album_size"
+ android:layout_marginTop="@dimen/qs_media_padding"
+ android:layout_marginBottom="@dimen/qs_media_padding"
+ app:layout_constraintTop_toBottomOf="@+id/media_cover2"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toEndOf="@+id/media_cover4"
+ app:layout_constraintEnd_toStartOf="@+id/media_cover6"
+ app:layout_constraintHorizontal_chainStyle="spread"
+ app:layout_constraintHorizontal_bias="1"
+ android:visibility="gone" />
+
+ <Constraint
+ android:id="@+id/media_logo5"
+ android:layout_width="@dimen/qs_media_icon_size"
+ android:layout_height="@dimen/qs_media_icon_size"
+ android:translationY="@dimen/qs_media_icon_offset"
+ android:translationX="@dimen/qs_media_icon_offset"
+ app:layout_constraintEnd_toEndOf="@+id/media_cover5"
+ app:layout_constraintBottom_toBottomOf="@+id/media_cover5"
+ android:visibility="gone" />
+
+ <Constraint
+ android:id="@+id/media_cover6"
+ android:layout_width="@dimen/qs_aa_media_rec_album_size"
+ android:layout_height="@dimen/qs_aa_media_rec_album_size"
+ android:layout_marginTop="@dimen/qs_media_padding"
+ android:layout_marginBottom="@dimen/qs_media_padding"
+ app:layout_constraintTop_toBottomOf="@id/media_cover3"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toEndOf="@id/media_cover5"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintHorizontal_chainStyle="spread"
+ app:layout_constraintHorizontal_bias="1"
+ android:visibility="gone" />
+
+ <Constraint
+ android:id="@+id/media_logo6"
+ android:layout_width="@dimen/qs_media_icon_size"
+ android:layout_height="@dimen/qs_media_icon_size"
+ android:translationY="@dimen/qs_media_icon_offset"
+ android:translationX="@dimen/qs_media_icon_offset"
+ app:layout_constraintEnd_toEndOf="@+id/media_cover6"
+ app:layout_constraintBottom_toBottomOf="@+id/media_cover6"
+ android:visibility="gone" />
+
+</ConstraintSet>
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 351dfd5..5708855 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
@@ -101,6 +101,9 @@
public RemoteTransitionCompat(RecentsAnimationListener recents,
RecentsAnimationControllerCompat controller) {
mTransition = new IRemoteTransition.Stub() {
+ final RecentsControllerWrap mRecentsSession = new RecentsControllerWrap();
+ IBinder mToken = null;
+
@Override
public void startAnimation(IBinder transition, TransitionInfo info,
SurfaceControl.Transaction t,
@@ -110,6 +113,7 @@
final RemoteAnimationTargetCompat[] wallpapers =
RemoteAnimationTargetCompat.wrap(info, true /* wallpapers */);
// 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
// the current going-away task on top of recents, though, so move it to front
WindowContainerToken pausingTask = null;
@@ -127,9 +131,8 @@
t.setAlpha(wallpapers[i].leash.mSurfaceControl, 1);
}
t.apply();
- final RecentsAnimationControllerCompat wrapControl =
- new RecentsControllerWrap(controller, info, finishedCallback, pausingTask);
- recents.onAnimationStart(wrapControl, apps, wallpapers, new Rect(0, 0, 0, 0),
+ mRecentsSession.setup(controller, info, finishedCallback, pausingTask);
+ recents.onAnimationStart(mRecentsSession, apps, wallpapers, new Rect(0, 0, 0, 0),
new Rect());
}
@@ -137,7 +140,13 @@
public void mergeAnimation(IBinder transition, TransitionInfo info,
SurfaceControl.Transaction t, IBinder mergeTarget,
IRemoteTransitionFinishedCallback finishedCallback) {
- // TODO: hook up merge to onTaskAppeared. Until then, just ignore incoming merges.
+ if (!mergeTarget.equals(mToken)) return;
+ if (!mRecentsSession.merge(info, t, recents)) return;
+ try {
+ finishedCallback.onTransitionFinished(null /* wct */);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error merging transition.", e);
+ }
}
};
}
@@ -159,19 +168,57 @@
*/
@VisibleForTesting
static class RecentsControllerWrap extends RecentsAnimationControllerCompat {
- private final RecentsAnimationControllerCompat mWrapped;
- private final IRemoteTransitionFinishedCallback mFinishCB;
- private final WindowContainerToken mPausingTask;
- private final TransitionInfo mInfo;
+ private RecentsAnimationControllerCompat mWrapped = null;
+ private IRemoteTransitionFinishedCallback mFinishCB = null;
+ private WindowContainerToken mPausingTask = null;
+ private TransitionInfo mInfo = null;
+ private SurfaceControl mOpeningLeash = null;
- RecentsControllerWrap(RecentsAnimationControllerCompat wrapped, TransitionInfo info,
+ void setup(RecentsAnimationControllerCompat wrapped, TransitionInfo info,
IRemoteTransitionFinishedCallback finishCB, WindowContainerToken pausingTask) {
+ if (mInfo != null) {
+ throw new IllegalStateException("Trying to run a new recents animation while"
+ + " recents is already active.");
+ }
mWrapped = wrapped;
mInfo = info;
mFinishCB = finishCB;
mPausingTask = pausingTask;
}
+ @SuppressLint("NewApi")
+ boolean merge(TransitionInfo info, SurfaceControl.Transaction t,
+ RecentsAnimationListener recents) {
+ TransitionInfo.Change openingTask = null;
+ for (int i = info.getChanges().size() - 1; i >= 0; --i) {
+ final TransitionInfo.Change change = info.getChanges().get(i);
+ if (change.getMode() == TRANSIT_OPEN || change.getMode() == TRANSIT_TO_FRONT) {
+ if (change.getTaskInfo() != null) {
+ if (openingTask != null) {
+ Log.w(TAG, " Expecting to merge a task-open, but got >1 opening "
+ + "tasks");
+ }
+ openingTask = change;
+ }
+ }
+ }
+ if (openingTask == null) return false;
+ mOpeningLeash = openingTask.getLeash();
+ if (openingTask.getContainer().equals(mPausingTask)) {
+ // In this case, we are "returning" to the already running app, so just consume
+ // the merge and do nothing.
+ return true;
+ }
+ // 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);
+ t.apply();
+ recents.onTaskAppeared(new RemoteAnimationTargetCompat(openingTask, layer));
+ return true;
+ }
+
@Override public ThumbnailData screenshotTask(int taskId) {
return mWrapped != null ? mWrapped.screenshotTask(taskId) : null;
}
@@ -198,25 +245,42 @@
@Override
@SuppressLint("NewApi")
public void finish(boolean toHome, boolean sendUserLeaveHint) {
+ if (mFinishCB == null) {
+ Log.e(TAG, "Duplicate call to finish", new RuntimeException());
+ return;
+ }
+ if (mWrapped != null) mWrapped.finish(toHome, sendUserLeaveHint);
try {
- if (!toHome && mPausingTask != null) {
+ if (!toHome && mPausingTask != null && mOpeningLeash == null) {
// The gesture went back to opening the app rather than continuing with
// recents, so end the transition by moving the app back to the top.
final WindowContainerTransaction wct = new WindowContainerTransaction();
wct.reorder(mPausingTask, true /* onTop */);
mFinishCB.onTransitionFinished(wct);
} else {
+ if (mOpeningLeash != null) {
+ // TODO: the launcher animation should handle this
+ final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+ t.show(mOpeningLeash);
+ t.setAlpha(mOpeningLeash, 1.f);
+ t.apply();
+ }
mFinishCB.onTransitionFinished(null /* wct */);
}
} catch (RemoteException e) {
Log.e("RemoteTransitionCompat", "Failed to call animation finish callback", e);
}
- if (mWrapped != null) mWrapped.finish(toHome, sendUserLeaveHint);
// Release surface references now. This is apparently to free GPU
// memory while doing quick operations (eg. during CTS).
for (int i = 0; i < mInfo.getChanges().size(); ++i) {
mInfo.getChanges().get(i).getLeash().release();
}
+ // Reset all members.
+ mWrapped = null;
+ mFinishCB = null;
+ mPausingTask = null;
+ mInfo = null;
+ mOpeningLeash = null;
}
@Override public void setDeferCancelUntilNextTransition(boolean defer, boolean screenshot) {
diff --git a/packages/SystemUI/src/com/android/keyguard/AnimatableClockView.java b/packages/SystemUI/src/com/android/keyguard/AnimatableClockView.java
index dc14f82..41d991c 100644
--- a/packages/SystemUI/src/com/android/keyguard/AnimatableClockView.java
+++ b/packages/SystemUI/src/com/android/keyguard/AnimatableClockView.java
@@ -42,7 +42,7 @@
private static final CharSequence DOUBLE_LINE_FORMAT_12_HOUR = "hh\nmm";
private static final CharSequence DOUBLE_LINE_FORMAT_24_HOUR = "HH\nmm";
private static final CharSequence SINGLE_LINE_FORMAT_12_HOUR = "h:mm";
- private static final CharSequence SINGLE_LINE_FORMAT_24_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 CHARGE_ANIM_DURATION_PHASE_0 = 500;
private static final long CHARGE_ANIM_DURATION_PHASE_1 = 1000;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
index 5b83551..e92cae4 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
@@ -24,8 +24,16 @@
import android.app.smartspace.SmartspaceConfig;
import android.app.smartspace.SmartspaceManager;
import android.app.smartspace.SmartspaceSession;
+import android.app.smartspace.SmartspaceTarget;
+import android.content.Context;
import android.content.Intent;
+import android.content.pm.UserInfo;
import android.content.res.Resources;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.provider.Settings;
import android.text.TextUtils;
import android.text.format.DateFormat;
import android.view.View;
@@ -47,6 +55,7 @@
import com.android.systemui.plugins.ClockPlugin;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.notification.AnimatableProperty;
import com.android.systemui.statusbar.notification.PropertyAnimator;
@@ -57,6 +66,7 @@
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.util.ViewController;
+import com.android.systemui.util.settings.SecureSettings;
import java.util.Locale;
import java.util.TimeZone;
@@ -96,6 +106,14 @@
private FalsingManager mFalsingManager;
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
private final KeyguardBypassController mBypassController;
+ private Handler mHandler;
+ private UserTracker mUserTracker;
+ private SecureSettings mSecureSettings;
+ private ContentObserver mSettingsObserver;
+ private boolean mShowSensitiveContentForCurrentUser;
+ private boolean mShowSensitiveContentForManagedUser;
+ private UserHandle mManagedUserHandle;
+ private UserTracker.Callback mUserTrackerCallback;
/**
* Listener for changes to the color palette.
@@ -151,7 +169,10 @@
ActivityStarter activityStarter,
FalsingManager falsingManager,
KeyguardUpdateMonitor keyguardUpdateMonitor,
- KeyguardBypassController bypassController) {
+ KeyguardBypassController bypassController,
+ @Main Handler handler,
+ UserTracker userTracker,
+ SecureSettings secureSettings) {
super(keyguardClockSwitch);
mStatusBarStateController = statusBarStateController;
mColorExtractor = colorExtractor;
@@ -168,6 +189,9 @@
mFalsingManager = falsingManager;
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mBypassController = bypassController;
+ mHandler = handler;
+ mUserTracker = userTracker;
+ mSecureSettings = secureSettings;
}
/**
@@ -258,15 +282,74 @@
mSmartspaceSession = getContext().getSystemService(SmartspaceManager.class)
.createSmartspaceSession(
new SmartspaceConfig.Builder(getContext(), "lockscreen").build());
- mSmartspaceCallback = targets -> smartspaceDataPlugin.onTargetsAvailable(targets);
+ mSmartspaceCallback = targets -> {
+ targets.removeIf(this::filterSmartspaceTarget);
+ smartspaceDataPlugin.onTargetsAvailable(targets);
+ };
mSmartspaceSession.addOnTargetsAvailableListener(mUiExecutor, mSmartspaceCallback);
- mSmartspaceSession.requestSmartspaceUpdate();
+ mSettingsObserver = new ContentObserver(mHandler) {
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ reloadSmartspace();
+ }
+ };
+
+ mUserTrackerCallback = new UserTracker.Callback() {
+ public void onUserChanged(int newUser, Context userContext) {
+ reloadSmartspace();
+ }
+ };
+ mUserTracker.addCallback(mUserTrackerCallback, mUiExecutor);
+
+ getContext().getContentResolver().registerContentObserver(
+ Settings.Secure.getUriFor(
+ Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS),
+ true, mSettingsObserver, UserHandle.USER_ALL);
+ reloadSmartspace();
}
float dozeAmount = mStatusBarStateController.getDozeAmount();
mStatusBarStateListener.onDozeAmountChanged(dozeAmount, dozeAmount);
}
+ @VisibleForTesting
+ boolean filterSmartspaceTarget(SmartspaceTarget t) {
+ if (!t.isSensitive()) return false;
+
+ if (t.getUserHandle().equals(mUserTracker.getUserHandle())) {
+ return !mShowSensitiveContentForCurrentUser;
+ }
+ if (t.getUserHandle().equals(mManagedUserHandle)) {
+ return !mShowSensitiveContentForManagedUser;
+ }
+
+ return false;
+ }
+
+ private void reloadSmartspace() {
+ mManagedUserHandle = getWorkProfileUser();
+ final String setting = Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS;
+
+ mShowSensitiveContentForCurrentUser =
+ mSecureSettings.getIntForUser(setting, 0, mUserTracker.getUserId()) == 1;
+ if (mManagedUserHandle != null) {
+ int id = mManagedUserHandle.getIdentifier();
+ mShowSensitiveContentForManagedUser =
+ mSecureSettings.getIntForUser(setting, 0, id) == 1;
+ }
+
+ mSmartspaceSession.requestSmartspaceUpdate();
+ }
+
+ private UserHandle getWorkProfileUser() {
+ for (UserInfo userInfo : mUserTracker.getUserProfiles()) {
+ if (userInfo.isManagedProfile()) {
+ return userInfo.getUserHandle();
+ }
+ }
+ return null;
+ }
+
private void updateWallpaperColor() {
if (mSmartspaceView != null) {
int color = Utils.getColorAttrDefaultColor(getContext(), R.attr.wallpaperTextColor);
@@ -289,6 +372,14 @@
}
mStatusBarStateController.removeCallback(mStatusBarStateListener);
mConfigurationController.removeCallback(mConfigurationListener);
+
+ if (mSettingsObserver != null) {
+ getContext().getContentResolver().unregisterContentObserver(mSettingsObserver);
+ }
+
+ if (mUserTrackerCallback != null) {
+ mUserTracker.removeCallback(mUserTrackerCallback);
+ }
}
/**
@@ -437,4 +528,9 @@
ConfigurationController.ConfigurationListener getConfigurationListener() {
return mConfigurationListener;
}
+
+ @VisibleForTesting
+ ContentObserver getSettingsObserver() {
+ return mSettingsObserver;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenu.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenu.java
index 7b4ce61..3b3bad3 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenu.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenu.java
@@ -70,9 +70,16 @@
}
};
+ private final ContentObserver mEnabledA11yServicesContentObserver =
+ new ContentObserver(mHandler) {
+ @Override
+ public void onChange(boolean selfChange) {
+ mMenuView.onEnabledFeaturesChanged();
+ }
+ };
+
public AccessibilityFloatingMenu(Context context) {
- mContext = context;
- mMenuView = new AccessibilityFloatingMenuView(context);
+ this(context, new AccessibilityFloatingMenuView(context));
}
@VisibleForTesting
@@ -153,11 +160,17 @@
Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_FLOATING_MENU_OPACITY),
/* notifyForDescendants */ false, mFadeOutContentObserver,
UserHandle.USER_CURRENT);
+ mContext.getContentResolver().registerContentObserver(
+ Settings.Secure.getUriFor(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES),
+ /* notifyForDescendants */ false,
+ mEnabledA11yServicesContentObserver, UserHandle.USER_CURRENT);
}
private void unregisterContentObservers() {
mContext.getContentResolver().unregisterContentObserver(mContentObserver);
mContext.getContentResolver().unregisterContentObserver(mSizeContentObserver);
mContext.getContentResolver().unregisterContentObserver(mFadeOutContentObserver);
+ mContext.getContentResolver().unregisterContentObserver(
+ mEnabledA11yServicesContentObserver);
}
}
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 5502a20..934e20d 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuView.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuView.java
@@ -24,6 +24,7 @@
import android.animation.ValueAnimator;
import android.annotation.IntDef;
import android.content.Context;
+import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.PixelFormat;
@@ -105,6 +106,7 @@
private float mRadius;
private float mPercentageY = LOCATION_Y_PERCENTAGE;
private float mSquareScaledTouchSlop;
+ private final Configuration mLastConfiguration;
private final RecyclerView mListView;
private final AccessibilityTargetAdapter mAdapter;
private float mFadeOutValue;
@@ -202,6 +204,8 @@
}
});
+ mLastConfiguration = new Configuration(getResources().getConfiguration());
+
updateDimensions();
initListView();
updateStrokeWith(getResources().getConfiguration().uiMode, mAlignment);
@@ -368,7 +372,7 @@
mTargets.clear();
mTargets.addAll(newTargets);
- mAdapter.notifyDataSetChanged();
+ onEnabledFeaturesChanged();
updateRadiusWith(mSizeType, mRadiusType, mTargets.size());
updateScrollModeWith(hasExceededMaxLayoutHeight());
@@ -416,6 +420,10 @@
setAlpha(mIsFadeEffectEnabled ? mFadeOutValue : /* completely opaque */ 1.0f);
}
+ void onEnabledFeaturesChanged() {
+ mAdapter.notifyDataSetChanged();
+ }
+
@VisibleForTesting
void fadeIn() {
if (!mIsFadeEffectEnabled) {
@@ -601,13 +609,17 @@
params.gravity = Gravity.START | Gravity.TOP;
params.x = getMaxWindowX();
params.y = (int) (getMaxWindowY() * mPercentageY);
-
+ updateAccessibilityTitle(params);
return params;
}
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
+ final int diff = newConfig.diff(mLastConfiguration);
+ if ((diff & ActivityInfo.CONFIG_LOCALE) != 0) {
+ updateAccessibilityTitle(mCurrentLayoutParams);
+ }
updateDimensions();
updateListView();
@@ -616,6 +628,8 @@
updateStrokeWith(newConfig.uiMode, mAlignment);
updateLocationWith(mAlignment, mPercentageY);
updateScrollModeWith(hasExceededMaxLayoutHeight());
+
+ mLastConfiguration.setTo(newConfig);
}
@VisibleForTesting
@@ -724,6 +738,11 @@
setInset(insetLeft, insetRight);
}
+ private void updateAccessibilityTitle(WindowManager.LayoutParams params) {
+ params.accessibilityTitle = getResources().getString(
+ com.android.internal.R.string.accessibility_select_shortcut_menu_title);
+ }
+
private void setInset(int left, int right) {
final LayerDrawable layerDrawable = getMenuLayerDrawable();
if (layerDrawable.getLayerInsetLeft(INDEX_MENU_ITEM) == left
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityTargetAdapter.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityTargetAdapter.java
index fd0c4ef..76106e7 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityTargetAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityTargetAdapter.java
@@ -24,9 +24,12 @@
import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
+import androidx.core.view.ViewCompat;
+import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.RecyclerView.Adapter;
+import com.android.internal.accessibility.common.ShortcutConstants.AccessibilityFragmentType;
import com.android.internal.accessibility.dialog.AccessibilityTarget;
import com.android.systemui.R;
import com.android.systemui.accessibility.floatingmenu.AccessibilityTargetAdapter.ViewHolder;
@@ -78,9 +81,20 @@
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
- holder.mIconView.setBackground(mTargets.get(position).getIcon());
+ final AccessibilityTarget target = mTargets.get(position);
+ holder.mIconView.setBackground(target.getIcon());
holder.updateIconWidthHeight(mIconWidthHeight);
- holder.itemView.setOnClickListener((v) -> mTargets.get(position).onSelected());
+ holder.itemView.setOnClickListener((v) -> target.onSelected());
+ holder.itemView.setStateDescription(target.getStateDescription());
+ holder.itemView.setContentDescription(target.getLabel());
+
+ final String clickHint = target.getFragmentType() == AccessibilityFragmentType.TOGGLE
+ ? holder.itemView.getResources().getString(
+ R.string.accessibility_floating_button_action_double_tap_to_toggle)
+ : null;
+ ViewCompat.replaceAccessibilityAction(holder.itemView,
+ AccessibilityNodeInfoCompat.AccessibilityActionCompat.ACTION_CLICK,
+ clickHint, /* command= */ null);
}
@ItemType
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
index 666afed..f1431f5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@@ -51,6 +51,7 @@
import com.android.internal.policy.IKeyguardService;
import com.android.internal.policy.IKeyguardStateCallback;
import com.android.systemui.SystemUIApplication;
+import com.android.wm.shell.transition.Transitions;
import javax.inject.Inject;
@@ -62,16 +63,29 @@
* Run Keyguard animation as remote animation in System UI instead of local animation in
* the server process.
*
+ * 0: Runs all keyguard animation as local animation
+ * 1: Only runs keyguard going away animation as remote animation
+ * 2: Runs all keyguard animation as remote animation
+ *
* Note: Must be consistent with WindowManagerService.
*/
private static final String ENABLE_REMOTE_KEYGUARD_ANIMATION_PROPERTY =
"persist.wm.enable_remote_keyguard_animation";
+ private static final int sEnableRemoteKeyguardAnimation =
+ SystemProperties.getInt(ENABLE_REMOTE_KEYGUARD_ANIMATION_PROPERTY, 1);
+
/**
* @see #ENABLE_REMOTE_KEYGUARD_ANIMATION_PROPERTY
*/
- static boolean sEnableRemoteKeyguardAnimation =
- SystemProperties.getBoolean(ENABLE_REMOTE_KEYGUARD_ANIMATION_PROPERTY, false);
+ public static boolean sEnableRemoteKeyguardGoingAwayAnimation =
+ !Transitions.ENABLE_SHELL_TRANSITIONS && sEnableRemoteKeyguardAnimation >= 1;
+
+ /**
+ * @see #ENABLE_REMOTE_KEYGUARD_ANIMATION_PROPERTY
+ */
+ public static boolean sEnableRemoteKeyguardOccludeAnimation =
+ !Transitions.ENABLE_SHELL_TRANSITIONS && sEnableRemoteKeyguardAnimation >= 2;
private final KeyguardViewMediator mKeyguardViewMediator;
private final KeyguardLifecyclesDispatcher mKeyguardLifecyclesDispatcher;
@@ -83,20 +97,22 @@
mKeyguardViewMediator = keyguardViewMediator;
mKeyguardLifecyclesDispatcher = keyguardLifecyclesDispatcher;
- if (sEnableRemoteKeyguardAnimation) {
- RemoteAnimationDefinition definition = new RemoteAnimationDefinition();
+ RemoteAnimationDefinition definition = new RemoteAnimationDefinition();
+ if (sEnableRemoteKeyguardGoingAwayAnimation) {
final RemoteAnimationAdapter exitAnimationAdapter =
new RemoteAnimationAdapter(mExitAnimationRunner, 0, 0);
definition.addRemoteAnimation(TRANSIT_OLD_KEYGUARD_GOING_AWAY, exitAnimationAdapter);
definition.addRemoteAnimation(TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER,
exitAnimationAdapter);
+ }
+ if (sEnableRemoteKeyguardOccludeAnimation) {
final RemoteAnimationAdapter occludeAnimationAdapter =
new RemoteAnimationAdapter(mOccludeAnimationRunner, 0, 0);
definition.addRemoteAnimation(TRANSIT_OLD_KEYGUARD_OCCLUDE, occludeAnimationAdapter);
definition.addRemoteAnimation(TRANSIT_OLD_KEYGUARD_UNOCCLUDE, occludeAnimationAdapter);
- ActivityTaskManager.getInstance().registerRemoteAnimationsForDisplay(
- DEFAULT_DISPLAY, definition);
}
+ ActivityTaskManager.getInstance().registerRemoteAnimationsForDisplay(
+ DEFAULT_DISPLAY, definition);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
index 411c328..85ee0dc 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
@@ -280,7 +280,7 @@
}
override fun onKeyguardDismissAmountChanged() {
- if (!KeyguardService.sEnableRemoteKeyguardAnimation) {
+ if (!KeyguardService.sEnableRemoteKeyguardGoingAwayAnimation) {
return
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 48f9a58..b7da7ad 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -2100,7 +2100,7 @@
playSounds(false);
}
- if (KeyguardService.sEnableRemoteKeyguardAnimation) {
+ if (KeyguardService.sEnableRemoteKeyguardGoingAwayAnimation) {
mSurfaceBehindRemoteAnimationFinishedCallback = finishedCallback;
mSurfaceBehindRemoteAnimationRunning = true;
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
index d87142f..8d9a4be 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
@@ -317,7 +317,7 @@
val lp = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT)
newRecs.recommendationViewHolder?.recommendations?.setLayoutParams(lp)
- newRecs.bindRecommendation(data, bgColor)
+ newRecs.bindRecommendation(data, fgColor, bgColor)
MediaPlayerData.addMediaPlayer(key, newRecs)
updatePlayerToState(newRecs, noAnimation = true)
reorderAllPlayers()
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
index 96ae2cd..c713b22 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
@@ -25,6 +25,7 @@
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.ColorStateList;
+import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
@@ -67,9 +68,9 @@
public class MediaControlPanel {
private static final String TAG = "MediaControlPanel";
private static final float DISABLED_ALPHA = 0.38f;
- private static final String EXTRAS_MEDIA_SOURCE_LOGO = "media_source_logo";
private static final String EXTRAS_MEDIA_SOURCE_PACKAGE_NAME = "package_name";
- private static final int MEDIA_RECOMMENDATION_MAX_NUM = 4;
+ private static final int MEDIA_RECOMMENDATION_ITEMS_PER_ROW = 3;
+ private static final int MEDIA_RECOMMENDATION_MAX_NUM = 6;
private static final Intent SETTINGS_INTENT = new Intent(ACTION_MEDIA_CONTROLS_SETTINGS);
@@ -456,11 +457,17 @@
}
/** Bind this recommendation view based on the data given. */
- public void bindRecommendation(@NonNull SmartspaceTarget target, @NonNull int backgroundColor) {
+ public void bindRecommendation(
+ @NonNull SmartspaceTarget target,
+ @NonNull int primaryColor,
+ @NonNull int backgroundColor) {
if (mRecommendationViewHolder == null) {
return;
}
+ mRecommendationViewHolder.getCardIcon().setColorFilter(primaryColor);
+ mRecommendationViewHolder.getCardText().setTextColor(primaryColor);
+
mRecommendationViewHolder.getRecommendations()
.setBackgroundTintList(ColorStateList.valueOf(backgroundColor));
mBackgroundColor = backgroundColor;
@@ -506,6 +513,8 @@
// Set up media source app's logo.
ImageView mediaSourceLogoImageView = mediaLogoItems.get(i);
mediaSourceLogoImageView.setImageDrawable(icon);
+ // TODO(b/186699032): Tint the app logo using the accent color.
+ mediaSourceLogoImageView.setColorFilter(backgroundColor, PorterDuff.Mode.XOR);
// Set up media item cover.
ImageView mediaCoverImageView = mediaCoverItems.get(i);
@@ -516,14 +525,17 @@
mediaCoverImageView,
recommendation,
target.getSmartspaceTargetId(),
- view -> mMediaDataManagerLazy
- .get()
- .dismissSmartspaceRecommendation(0L /* delay */));
+ null);
+ if (i < MEDIA_RECOMMENDATION_ITEMS_PER_ROW) {
+ setVisibleAndAlpha(collapsedSet, mediaCoverItemsResIds.get(i), true);
+ setVisibleAndAlpha(collapsedSet, mediaLogoItemsResIds.get(i), true);
+ } else {
+ setVisibleAndAlpha(collapsedSet, mediaCoverItemsResIds.get(i), false);
+ setVisibleAndAlpha(collapsedSet, mediaLogoItemsResIds.get(i), false);
+ }
setVisibleAndAlpha(expandedSet, mediaCoverItemsResIds.get(i), true);
setVisibleAndAlpha(expandedSet, mediaLogoItemsResIds.get(i), true);
- setVisibleAndAlpha(collapsedSet, mediaCoverItemsResIds.get(i), true);
- setVisibleAndAlpha(collapsedSet, mediaLogoItemsResIds.get(i), true);
}
// Set up long press to show guts setting panel.
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt
index 9163044..e5c15107 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt
@@ -25,6 +25,7 @@
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.settings.CurrentUserTracker
import com.android.systemui.statusbar.NotificationLockscreenUserManager
+import com.android.systemui.util.time.SystemClock
import java.util.concurrent.Executor
import java.util.concurrent.TimeUnit
import javax.inject.Inject
@@ -36,7 +37,8 @@
* Maximum age of a media control to re-activate on smartspace signal. If there is no media control
* available within this time window, smartspace recommendations will be shown instead.
*/
-private val SMARTSPACE_MAX_AGE = SystemProperties
+@VisibleForTesting
+internal val SMARTSPACE_MAX_AGE = SystemProperties
.getLong("debug.sysui.smartspace_max_age", TimeUnit.HOURS.toMillis(3))
/**
@@ -51,7 +53,8 @@
private val broadcastDispatcher: BroadcastDispatcher,
private val mediaResumeListener: MediaResumeListener,
private val lockscreenUserManager: NotificationLockscreenUserManager,
- @Main private val executor: Executor
+ @Main private val executor: Executor,
+ private val systemClock: SystemClock
) : MediaDataManager.Listener {
private val userTracker: CurrentUserTracker
private val _listeners: MutableSet<MediaDataManager.Listener> = mutableSetOf()
@@ -100,7 +103,7 @@
hasSmartspace = true
// Before forwarding the smartspace target, first check if we have recently inactive media
- val now = System.currentTimeMillis()
+ val now = systemClock.elapsedRealtime()
val sorted = userEntries.toSortedMap(compareBy {
userEntries.get(it)?.lastActive ?: -1
})
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
index 138c422..a45bd33 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
@@ -56,6 +56,7 @@
import com.android.systemui.util.Assert
import com.android.systemui.util.Utils
import com.android.systemui.util.concurrency.DelayableExecutor
+import com.android.systemui.util.time.SystemClock
import java.io.FileDescriptor
import java.io.IOException
import java.io.PrintWriter
@@ -108,7 +109,8 @@
private val activityStarter: ActivityStarter,
private val smartspaceMediaDataProvider: SmartspaceMediaDataProvider,
private var useMediaResumption: Boolean,
- private val useQsMediaPlayer: Boolean
+ private val useQsMediaPlayer: Boolean,
+ private val systemClock: SystemClock
) : Dumpable, BcSmartspaceDataPlugin.SmartspaceTargetListener {
companion object {
@@ -164,12 +166,13 @@
mediaDataCombineLatest: MediaDataCombineLatest,
mediaDataFilter: MediaDataFilter,
activityStarter: ActivityStarter,
- smartspaceMediaDataProvider: SmartspaceMediaDataProvider
+ smartspaceMediaDataProvider: SmartspaceMediaDataProvider,
+ clock: SystemClock
) : this(context, backgroundExecutor, foregroundExecutor, mediaControllerFactory,
broadcastDispatcher, dumpManager, mediaTimeoutListener, mediaResumeListener,
mediaSessionBasedFilter, mediaDeviceManager, mediaDataCombineLatest, mediaDataFilter,
activityStarter, smartspaceMediaDataProvider, Utils.useMediaResumption(context),
- Utils.useQsMediaPlayer(context))
+ Utils.useQsMediaPlayer(context), clock)
private val appChangeReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
@@ -474,7 +477,7 @@
}
val mediaAction = getResumeMediaAction(resumeAction)
- val lastActive = System.currentTimeMillis()
+ val lastActive = systemClock.elapsedRealtime()
foregroundExecutor.execute {
onMediaDataLoaded(packageName, null, MediaData(userId, true, bgColor, appName,
null, desc.subtitle, desc.title, artworkIcon, listOf(mediaAction), listOf(0),
@@ -597,7 +600,7 @@
val isLocalSession = mediaController.playbackInfo?.playbackType ==
MediaController.PlaybackInfo.PLAYBACK_TYPE_LOCAL
val isPlaying = mediaController.playbackState?.let { isPlayingState(it.state) } ?: null
- val lastActive = System.currentTimeMillis()
+ val lastActive = systemClock.elapsedRealtime()
foregroundExecutor.execute {
val resumeAction: Runnable? = mediaEntries[key]?.resumeAction
val hasCheckedForResume = mediaEntries[key]?.hasCheckedForResume == true
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaViewController.kt b/packages/SystemUI/src/com/android/systemui/media/MediaViewController.kt
index f78556f..50d6e12 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaViewController.kt
@@ -466,8 +466,8 @@
collapsedLayout.load(context, R.xml.media_collapsed)
expandedLayout.load(context, R.xml.media_expanded)
} else {
- collapsedLayout.load(context, R.xml.media_recommendation)
- expandedLayout.load(context, R.xml.media_recommendation)
+ collapsedLayout.load(context, R.xml.media_recommendation_collapsed)
+ expandedLayout.load(context, R.xml.media_recommendation_expanded)
}
refreshState()
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/RecommendationViewHolder.kt b/packages/SystemUI/src/com/android/systemui/media/RecommendationViewHolder.kt
index 02150c4..3d0e653 100644
--- a/packages/SystemUI/src/com/android/systemui/media/RecommendationViewHolder.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/RecommendationViewHolder.kt
@@ -20,6 +20,7 @@
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
+import android.widget.TextView
import androidx.annotation.IntegerRes
import com.android.systemui.R
import com.android.systemui.util.animation.TransitionLayout
@@ -30,26 +31,36 @@
val recommendations = itemView as TransitionLayout
// Recommendation screen
+ val cardIcon = itemView.requireViewById<ImageView>(R.id.recommendation_card_icon)
+ val cardText = itemView.requireViewById<TextView>(R.id.recommendation_card_text)
val mediaCoverItems = listOf<ImageView>(
itemView.requireViewById(R.id.media_cover1),
itemView.requireViewById(R.id.media_cover2),
itemView.requireViewById(R.id.media_cover3),
- itemView.requireViewById(R.id.media_cover4))
+ itemView.requireViewById(R.id.media_cover4),
+ itemView.requireViewById(R.id.media_cover5),
+ itemView.requireViewById(R.id.media_cover6))
val mediaLogoItems = listOf<ImageView>(
itemView.requireViewById(R.id.media_logo1),
itemView.requireViewById(R.id.media_logo2),
itemView.requireViewById(R.id.media_logo3),
- itemView.requireViewById(R.id.media_logo4))
+ itemView.requireViewById(R.id.media_logo4),
+ itemView.requireViewById(R.id.media_logo5),
+ itemView.requireViewById(R.id.media_logo6))
val mediaCoverItemsResIds = listOf<@IntegerRes Int>(
R.id.media_cover1,
R.id.media_cover2,
R.id.media_cover3,
- R.id.media_cover4)
+ R.id.media_cover4,
+ R.id.media_cover5,
+ R.id.media_cover6)
val mediaLogoItemsResIds = listOf<@IntegerRes Int>(
R.id.media_logo1,
R.id.media_logo2,
R.id.media_logo3,
- R.id.media_logo4)
+ R.id.media_logo4,
+ R.id.media_logo5,
+ R.id.media_logo6)
// Settings/Guts screen
val cancel = itemView.requireViewById<View>(R.id.cancel)
@@ -91,14 +102,20 @@
// Res Ids for the control components on the recommendation view.
val controlsIds = setOf(
+ R.id.recommendation_card_icon,
+ R.id.recommendation_card_text,
R.id.media_cover1,
R.id.media_cover2,
R.id.media_cover3,
R.id.media_cover4,
+ R.id.media_cover5,
+ R.id.media_cover6,
R.id.media_logo1,
R.id.media_logo2,
R.id.media_logo3,
- R.id.media_logo4
+ R.id.media_logo4,
+ R.id.media_logo5,
+ R.id.media_logo6
)
// Res Ids for the components on the guts panel.
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
index 56375ad..4e41d75 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
@@ -101,6 +101,7 @@
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener;
+import android.view.inputmethod.InputMethodManager;
import androidx.annotation.VisibleForTesting;
@@ -1175,6 +1176,9 @@
accessibilityButton.setOnLongClickListener(this::onAccessibilityLongClick);
updateAccessibilityServicesState(mAccessibilityManager);
+ ButtonDispatcher imeSwitcherButton = mNavigationBarView.getImeSwitchButton();
+ imeSwitcherButton.setOnClickListener(this::onImeSwitcherClick);
+
updateScreenPinningGestures();
}
@@ -1274,6 +1278,11 @@
mCommandQueue.toggleRecentApps();
}
+ private void onImeSwitcherClick(View v) {
+ mContext.getSystemService(InputMethodManager.class).showInputMethodPickerFromSystem(
+ true /* showAuxiliarySubtypes */, mDisplayId);
+ };
+
private boolean onLongPressBackHome(View v) {
return onLongPressNavigationButtons(v, R.id.back, R.id.home);
}
@@ -1282,7 +1291,6 @@
return onLongPressNavigationButtons(v, R.id.back, R.id.recent_apps);
}
-
/**
* This handles long-press of both back and recents/home. Back is the common button with
* combination of recents if it is visible or home if recents is invisible.
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
index 3544f60..66cfae4 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
@@ -217,6 +217,9 @@
@Override
public void onNavigationModeChanged(int mode) {
+ if (mNavMode == mode) {
+ return;
+ }
final int oldMode = mNavMode;
mNavMode = mode;
mHandler.post(() -> {
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarInflaterView.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarInflaterView.java
index 7342f91..4d9175b 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarInflaterView.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarInflaterView.java
@@ -158,7 +158,6 @@
}
public void onLikelyDefaultLayoutChange() {
-
// Reevaluate new layout
final String newValue = getDefaultLayout();
if (!Objects.equals(mCurrentLayout, newValue)) {
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
index 0ed4d86..bdd2735 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
@@ -166,6 +166,7 @@
private NavigationBarInflaterView mNavigationInflaterView;
private RecentsOnboarding mRecentsOnboarding;
private NotificationPanelViewController mPanelView;
+ private RotationContextButton mRotationContextButton;
private FloatingRotationButton mFloatingRotationButton;
private RotationButtonController mRotationButtonController;
private NavigationBarOverlayController mNavBarOverlayController;
@@ -233,14 +234,6 @@
}
}
- private final OnClickListener mImeSwitcherClickListener = new OnClickListener() {
- @Override
- public void onClick(View view) {
- mContext.getSystemService(InputMethodManager.class).showInputMethodPickerFromSystem(
- true /* showAuxiliarySubtypes */, getContext().getDisplayId());
- }
- };
-
private final AccessibilityDelegate mQuickStepAccessibilityDelegate =
new AccessibilityDelegate() {
private AccessibilityAction mToggleOverviewAction;
@@ -311,32 +304,26 @@
mIsVertical = false;
mLongClickableAccessibilityButton = false;
mNavBarMode = Dependency.get(NavigationModeController.class).addListener(this);
- boolean isGesturalMode = isGesturalMode(mNavBarMode);
mSysUiFlagContainer = Dependency.get(SysUiState.class);
// Set up the context group of buttons
mContextualButtonGroup = new ContextualButtonGroup(R.id.menu_container);
final ContextualButton imeSwitcherButton = new ContextualButton(R.id.ime_switcher,
mLightContext, R.drawable.ic_ime_switcher_default);
- final RotationContextButton rotateSuggestionButton = new RotationContextButton(
- R.id.rotate_suggestion, mLightContext,
- R.drawable.ic_sysbar_rotate_button_ccw_start_0);
final ContextualButton accessibilityButton =
new ContextualButton(R.id.accessibility_button, mLightContext,
R.drawable.ic_sysbar_accessibility_button);
mContextualButtonGroup.addButton(imeSwitcherButton);
- if (!isGesturalMode) {
- mContextualButtonGroup.addButton(rotateSuggestionButton);
- }
mContextualButtonGroup.addButton(accessibilityButton);
mOverviewProxyService = Dependency.get(OverviewProxyService.class);
+ mRotationContextButton = new RotationContextButton(R.id.rotate_suggestion,
+ mLightContext, R.drawable.ic_sysbar_rotate_button_ccw_start_0);
mFloatingRotationButton = new FloatingRotationButton(context);
mRecentsOnboarding = new RecentsOnboarding(context, mOverviewProxyService);
mRotationButtonController = new RotationButtonController(mLightContext,
- mLightIconColor, mDarkIconColor,
- isGesturalMode ? mFloatingRotationButton : rotateSuggestionButton,
- mRotationButtonListener);
+ mLightIconColor, mDarkIconColor);
+ updateRotationButton();
mNavBarOverlayController = Dependency.get(NavigationBarOverlayController.class);
if (mNavBarOverlayController.isNavigationBarOverlayEnabled()) {
@@ -357,7 +344,6 @@
mButtonDispatchers.put(R.id.recent_apps, new ButtonDispatcher(R.id.recent_apps));
mButtonDispatchers.put(R.id.ime_switcher, imeSwitcherButton);
mButtonDispatchers.put(R.id.accessibility_button, accessibilityButton);
- mButtonDispatchers.put(R.id.rotate_suggestion, rotateSuggestionButton);
mButtonDispatchers.put(R.id.menu_container, mContextualButtonGroup);
mDeadZone = new DeadZone(this);
@@ -555,6 +541,23 @@
}
}
+ /**
+ * Updates the rotation button based on the current navigation mode.
+ */
+ private void updateRotationButton() {
+ if (isGesturalMode(mNavBarMode)) {
+ mContextualButtonGroup.removeButton(R.id.rotate_suggestion);
+ mButtonDispatchers.remove(R.id.rotate_suggestion);
+ mRotationButtonController.setRotationButton(mFloatingRotationButton,
+ mRotationButtonListener);
+ } else if (mContextualButtonGroup.getContextButton(R.id.rotate_suggestion) == null) {
+ mContextualButtonGroup.addButton(mRotationContextButton);
+ mButtonDispatchers.put(R.id.rotate_suggestion, mRotationContextButton);
+ mRotationButtonController.setRotationButton(mRotationContextButton,
+ mRotationButtonListener);
+ }
+ }
+
public KeyButtonDrawable getBackDrawable() {
KeyButtonDrawable drawable = getDrawable(getBackDrawableRes());
orientBackButton(drawable);
@@ -908,6 +911,7 @@
mBarTransitions.onNavigationModeChanged(mNavBarMode);
mEdgeBackGestureHandler.onNavigationModeChanged(mNavBarMode);
mRecentsOnboarding.onNavigationModeChanged(mNavBarMode);
+ updateRotationButton();
if (isGesturalMode(mNavBarMode)) {
mRegionSamplingHelper.start(mSamplingBounds);
@@ -932,7 +936,6 @@
mNavigationInflaterView = findViewById(R.id.navigation_inflater);
mNavigationInflaterView.setButtonDispatchers(mButtonDispatchers);
- getImeSwitchButton().setOnClickListener(mImeSwitcherClickListener);
updateOrientationViews();
reloadNavIcons();
}
@@ -1027,6 +1030,9 @@
private void updateButtonLocation(ButtonDispatcher button, boolean inScreenSpace,
boolean useNearestRegion) {
+ if (button == null) {
+ return;
+ }
View view = button.getCurrentView();
if (view == null || !button.isVisible()) {
return;
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/RotationButtonController.java b/packages/SystemUI/src/com/android/systemui/navigationbar/RotationButtonController.java
index 4bcb019..ddf089b 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/RotationButtonController.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/RotationButtonController.java
@@ -66,10 +66,10 @@
private static final int NUM_ACCEPTED_ROTATION_SUGGESTIONS_FOR_INTRODUCTION = 3;
private final Context mContext;
- private final RotationButton mRotationButton;
private final Handler mMainThreadHandler = new Handler(Looper.getMainLooper());
private final UiEventLogger mUiEventLogger = new UiEventLoggerImpl();
private final ViewRippler mViewRippler = new ViewRippler();
+ private RotationButton mRotationButton;
private int mLastRotationSuggestion;
private boolean mPendingRotationSuggestion;
@@ -125,20 +125,21 @@
}
RotationButtonController(Context context, @ColorInt int lightIconColor,
- @ColorInt int darkIconColor, RotationButton rotationButton,
- Consumer<Boolean> visibilityChangedCallback) {
+ @ColorInt int darkIconColor) {
mContext = context;
mLightIconColor = lightIconColor;
mDarkIconColor = darkIconColor;
- mRotationButton = rotationButton;
- mRotationButton.setRotationButtonController(this);
mIsNavigationBarShowing = true;
mRotationLockController = Dependency.get(RotationLockController.class);
mAccessibilityManagerWrapper = Dependency.get(AccessibilityManagerWrapper.class);
-
- // Register the task stack listener
mTaskStackListener = new TaskStackListenerImpl();
+ }
+
+ void setRotationButton(RotationButton rotationButton,
+ Consumer<Boolean> visibilityChangedCallback) {
+ mRotationButton = rotationButton;
+ mRotationButton.setRotationButtonController(this);
mRotationButton.setOnClickListener(this::onRotateSuggestionClick);
mRotationButton.setOnHoverListener(this::onRotateSuggestionHover);
mRotationButton.setVisibilityChangedCallback(visibilityChangedCallback);
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/ContextualButtonGroup.java b/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/ContextualButtonGroup.java
index 50b638b..2ace303 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/ContextualButtonGroup.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/ContextualButtonGroup.java
@@ -41,10 +41,23 @@
* @param button the button added to the group
*/
public void addButton(@NonNull ContextualButton button) {
+ // By default buttons in the context group are not visible until
+ // {@link #setButtonVisibility()) is called to show one of the buttons
+ button.setVisibility(View.INVISIBLE);
button.attachToGroup(this);
mButtonData.add(new ButtonData(button));
}
+ /**
+ * Removes a contextual button from the group.
+ */
+ public void removeButton(@IdRes int buttonResId) {
+ int index = getContextButtonIndex(buttonResId);
+ if (index != INVALID_INDEX) {
+ mButtonData.remove(index);
+ }
+ }
+
public ContextualButton getContextButton(@IdRes int buttonResId) {
int index = getContextButtonIndex(buttonResId);
if (index != INVALID_INDEX) {
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
index 8b27b6e..e072b4a 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
@@ -151,7 +151,9 @@
return
}
val userId = UserHandle.getUserId(uid)
- if (userId in currentUserIds) {
+ if (userId in currentUserIds ||
+ code == AppOpsManager.OP_PHONE_CALL_MICROPHONE ||
+ code == AppOpsManager.OP_PHONE_CALL_CAMERA) {
logger.logUpdatedItemFromAppOps(code, uid, packageName, active)
update(false)
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
index 488ada9..be96ba8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
@@ -35,6 +35,7 @@
import com.android.systemui.statusbar.CrossFadeHelper;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
+import com.android.wm.shell.animation.Interpolators;
import java.util.ArrayList;
import java.util.Collection;
@@ -374,11 +375,14 @@
// Make brightness appear static position and alpha in through second half.
View brightness = mQsPanelController.getBrightnessView();
if (brightness != null) {
- firstPageBuilder.addFloat(brightness, "translationY", heightDiff, 0);
+ firstPageBuilder.addFloat(brightness, "translationY",
+ brightness.getMeasuredHeight() * 0.5f, 0);
mBrightnessAnimator = new TouchAnimator.Builder()
.addFloat(brightness, "alpha", 0, 1)
- .setStartDelay(.5f)
+ .addFloat(brightness, "scaleY", 0.3f, 1)
+ .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
.build();
+ brightness.setPivotY(0);
mAllViews.add(brightness);
} else {
mBrightnessAnimator = null;
@@ -476,9 +480,6 @@
mFirstPageAnimator.setPosition(position);
mFirstPageDelayedAnimator.setPosition(position);
mTranslationYAnimator.setPosition(position);
- if (mBrightnessAnimator != null) {
- mBrightnessAnimator.setPosition(position);
- }
if (mQQSTileHeightAnimator != null) {
mQQSTileHeightAnimator.setPosition(position);
}
@@ -491,6 +492,9 @@
}
if (mAllowFancy) {
mAllPagesDelayedAnimator.setPosition(position);
+ if (mBrightnessAnimator != null) {
+ mBrightnessAnimator.setPosition(position);
+ }
}
}
@@ -527,6 +531,7 @@
v.setAlpha(1);
v.setTranslationX(0);
v.setTranslationY(0);
+ v.setScaleY(1f);
if (v instanceof SideLabelTileLayout) {
((SideLabelTileLayout) v).setClipChildren(false);
((SideLabelTileLayout) v).setClipToPadding(false);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
index 9abb430..f486c53 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
@@ -60,7 +60,7 @@
private int mFancyClippingBottom;
private final float[] mFancyClippingRadii = new float[] {0, 0, 0, 0, 0, 0, 0, 0};
private final Path mFancyClippingPath = new Path();
- private int mBackgroundBottom = -1;
+ private int mBackgroundBottom = 0;
private int mHeightOverride = -1;
private View mQSDetail;
private QuickStatusBarHeader mHeader;
@@ -68,11 +68,8 @@
private QSCustomizer mQSCustomizer;
private NonInterceptingScrollView mQSPanelContainer;
- private View mBackground;
-
private int mSideMargins;
private boolean mQsDisabled;
- private boolean mBackgroundVisible;
private int mContentPadding = -1;
private boolean mAnimateBottomOnNextLayout;
private int mNavBarInset = 0;
@@ -89,7 +86,6 @@
mQSDetail = findViewById(R.id.qs_detail);
mHeader = findViewById(R.id.header);
mQSCustomizer = findViewById(R.id.qs_customize);
- mBackground = findViewById(R.id.quick_settings_background);
mHeader.getHeaderQsPanel().setMediaVisibilityChangedListener((visible) -> {
if (mHeader.getHeaderQsPanel().isShown()) {
mAnimateBottomOnNextLayout = true;
@@ -111,13 +107,9 @@
// We're saving the bottom separately since otherwise the bottom would be overridden in
// the layout and the animation wouldn't properly start at the old position.
mBackgroundBottom = value;
- mBackground.setBottom(value);
}
private float getBackgroundBottom() {
- if (mBackgroundBottom == -1) {
- return mBackground.getBottom();
- }
return mBackgroundBottom;
}
@@ -134,14 +126,6 @@
return true;
}
- /**
- * If QS should have a solid or transparent background.
- */
- public void setBackgroundVisible(boolean visible) {
- mBackgroundVisible = visible;
- updateBackgroundVisibility();
- }
-
@Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
mNavBarInset = insets.getInsets(WindowInsets.Type.navigationBars()).bottom;
@@ -208,11 +192,6 @@
final boolean disabled = (state2 & DISABLE2_QUICK_SETTINGS) != 0;
if (disabled == mQsDisabled) return;
mQsDisabled = disabled;
- updateBackgroundVisibility();
- }
-
- private void updateBackgroundVisibility() {
- mBackground.setVisibility(mQsDisabled || !mBackgroundVisible ? GONE : VISIBLE);
}
void updateResources(QSPanelController qsPanelController,
@@ -260,7 +239,6 @@
mQSDetail.setBottom(getTop() + scrollBottom);
int qsDetailBottomMargin = ((MarginLayoutParams) mQSDetail.getLayoutParams()).bottomMargin;
mQSDetail.setBottom(getTop() + scrollBottom - qsDetailBottomMargin);
- mBackground.setTop(mQSPanelContainer.getTop());
updateBackgroundBottom(scrollBottom, animate);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index 814846c..53b4d5f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -172,7 +172,6 @@
mQSContainerImplController = qsFragmentComponent.getQSContainerImplController();
mQSContainerImplController.init();
mContainer = mQSContainerImplController.getView();
- mContainer.setBackgroundVisible(!mFeatureFlags.isShadeOpaque());
mQSDetail.setQsPanel(mQSPanelController, mHeader, mFooter);
mQSAnimator = qsFragmentComponent.getQSAnimator();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/TouchAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/TouchAnimator.java
index f673364..ca8f681 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/TouchAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/TouchAnimator.java
@@ -53,6 +53,7 @@
}
public void setPosition(float fraction) {
+ if (Float.isNaN(fraction)) return;
float t = MathUtils.constrain((fraction - mStartDelay) / mSpan, 0, 1);
if (mInterpolator != null) {
t = mInterpolator.getInterpolation(t);
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 ff830bc..be40423 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java
@@ -129,8 +129,15 @@
Intent intent = new Intent(mContext, WalletActivity.class)
.setAction(Intent.ACTION_VIEW)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
- mActivityStarter.startActivity(intent, true /* dismissShade */,
- animationController);
+ if (mKeyguardStateController.isUnlocked()) {
+ mActivityStarter.startActivity(intent, true /* dismissShade */,
+ animationController);
+ } else {
+ mHost.collapsePanels();
+ // Do not use ActivityStarter here because the WalletActivity is required to be
+ // started without prompting keyguard when the device is locked.
+ mContext.startActivity(intent);
+ }
} else {
if (mQuickAccessWalletClient.createWalletIntent() == null) {
Log.w(TAG, "Could not get intent of the wallet app.");
@@ -147,7 +154,7 @@
protected void handleUpdateState(State state, Object arg) {
state.label = mLabel;
state.contentDescription = state.label;
- state.icon = ResourceIcon.get(R.drawable.ic_qs_wallet);
+ state.icon = ResourceIcon.get(R.drawable.ic_wallet_lockscreen);
boolean isDeviceLocked = !mKeyguardStateController.isUnlocked();
if (mQuickAccessWalletClient.isWalletServiceAvailable()) {
if (mHasCard) {
@@ -219,7 +226,12 @@
refreshState();
return;
}
- mCardViewDrawable = cards.get(0).getCardImage().loadDrawable(mContext);
+ int selectedIndex = response.getSelectedIndex();
+ if (selectedIndex >= cards.size()) {
+ Log.d(TAG, "Selected card index out of bounds.");
+ return;
+ }
+ mCardViewDrawable = cards.get(selectedIndex).getCardImage().loadDrawable(mContext);
mHasCard = true;
refreshState();
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index 850f8a5..f078ccd 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -408,6 +408,7 @@
mPipOptional.ifPresent(
pip -> pip.setPinnedStackAnimationType(
PipAnimationController.ANIM_TYPE_ALPHA));
+ mHandler.post(() -> notifySwipeToHomeFinishedInternal());
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -886,6 +887,12 @@
}
}
+ public void notifySwipeToHomeFinishedInternal() {
+ for (int i = mConnectionCallbacks.size() - 1; i >= 0; --i) {
+ mConnectionCallbacks.get(i).onSwipeToHomeFinished();
+ }
+ }
+
public void notifyAssistantVisibilityChanged(float visibility) {
try {
if (mOverviewProxy != null) {
@@ -962,6 +969,7 @@
public interface OverviewProxyListener {
default void onConnectionChanged(boolean isConnected) {}
default void onQuickStepStarted() {}
+ default void onSwipeToHomeFinished() {}
default void onQuickSwitchToNewTask(@Surface.Rotation int rotation) {}
default void onOverviewShown(boolean fromHome) {}
default void onQuickScrubStarted() {}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java b/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java
index 17b489c..d96e1ba 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java
@@ -44,10 +44,6 @@
return mFlagReader.isEnabled(R.bool.flag_notification_pipeline2_rendering);
}
- public boolean isShadeOpaque() {
- return mFlagReader.isEnabled(R.bool.flag_shade_is_opaque);
- }
-
/** b/171917882 */
public boolean isTwoColumnNotificationShadeEnabled() {
return mFlagReader.isEnabled(R.bool.flag_notification_twocolumn);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
index 7f31fdd..5437ce6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
@@ -18,7 +18,6 @@
import static com.android.systemui.statusbar.RemoteInputController.processForRemoteInput;
import static com.android.systemui.statusbar.notification.NotificationEntryManager.UNDEFINED_DISMISS_REASON;
-import static com.android.systemui.statusbar.phone.StatusBar.DEBUG;
import android.annotation.NonNull;
import android.annotation.SuppressLint;
@@ -35,6 +34,7 @@
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.statusbar.dagger.StatusBarModule;
import com.android.systemui.statusbar.phone.NotificationListenerWithPlugins;
+import com.android.systemui.statusbar.phone.StatusBar;
import java.util.ArrayList;
import java.util.List;
@@ -46,6 +46,7 @@
@SuppressLint("OverrideAbstract")
public class NotificationListener extends NotificationListenerWithPlugins {
private static final String TAG = "NotificationListener";
+ private static final boolean DEBUG = StatusBar.DEBUG;
private final Context mContext;
private final NotificationManager mNotificationManager;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt
index c85b62f..8194220 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt
@@ -6,6 +6,7 @@
import com.android.systemui.statusbar.NotificationShadeDepthController
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.stack.NotificationListContainer
+import com.android.systemui.statusbar.phone.HeadsUpManagerPhone
import com.android.systemui.statusbar.phone.NotificationShadeWindowViewController
import kotlin.math.ceil
import kotlin.math.max
@@ -14,7 +15,8 @@
class NotificationLaunchAnimatorControllerProvider(
private val notificationShadeWindowViewController: NotificationShadeWindowViewController,
private val notificationListContainer: NotificationListContainer,
- private val depthController: NotificationShadeDepthController
+ private val depthController: NotificationShadeDepthController,
+ private val headsUpManager: HeadsUpManagerPhone
) {
fun getAnimatorController(
notification: ExpandableNotificationRow
@@ -23,7 +25,8 @@
notificationShadeWindowViewController,
notificationListContainer,
depthController,
- notification
+ notification,
+ headsUpManager
)
}
}
@@ -37,8 +40,11 @@
private val notificationShadeWindowViewController: NotificationShadeWindowViewController,
private val notificationListContainer: NotificationListContainer,
private val depthController: NotificationShadeDepthController,
- private val notification: ExpandableNotificationRow
+ private val notification: ExpandableNotificationRow,
+ private val headsUpManager: HeadsUpManagerPhone
) : ActivityLaunchAnimator.Controller {
+ private val notificationKey = notification.entry.sbn.key
+
override fun getRootView(): View = notification.rootView
override fun createAnimatorState(): ActivityLaunchAnimator.State {
@@ -76,12 +82,25 @@
override fun onIntentStarted(willAnimate: Boolean) {
notificationShadeWindowViewController.setExpandAnimationRunning(willAnimate)
+
+ if (!willAnimate) {
+ removeHun(animate = true)
+ }
+ }
+
+ private fun removeHun(animate: Boolean) {
+ if (!headsUpManager.isAlerting(notificationKey)) {
+ return
+ }
+
+ headsUpManager.removeNotification(notificationKey, true /* releaseImmediately */, animate)
}
override fun onLaunchAnimationCancelled() {
// TODO(b/184121838): Should we call InteractionJankMonitor.cancel if the animation started
// here?
notificationShadeWindowViewController.setExpandAnimationRunning(false)
+ removeHun(animate = true)
}
override fun onLaunchAnimationStart(isExpandingFullyAbove: Boolean) {
@@ -99,6 +118,7 @@
notificationShadeWindowViewController.setExpandAnimationRunning(false)
notificationListContainer.setExpandingNotification(null)
applyParams(null)
+ removeHun(animate = false)
}
private fun applyParams(params: ExpandAnimationParameters?) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/NotificationGroupManagerLegacy.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/NotificationGroupManagerLegacy.java
index d6356de..d95c265 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/NotificationGroupManagerLegacy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/NotificationGroupManagerLegacy.java
@@ -16,7 +16,9 @@
package com.android.systemui.statusbar.notification.collection.legacy;
+import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.Notification;
import android.service.notification.StatusBarNotification;
import android.util.ArraySet;
import android.util.Log;
@@ -31,6 +33,7 @@
import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager;
import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
+import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
import com.android.wm.shell.bubbles.Bubbles;
@@ -39,10 +42,12 @@
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
+import java.util.TreeSet;
import javax.inject.Inject;
@@ -58,13 +63,21 @@
public class NotificationGroupManagerLegacy implements OnHeadsUpChangedListener, StateListener,
GroupMembershipManager, GroupExpansionManager, Dumpable {
- private static final String TAG = "NotificationGroupManager";
+ private static final String TAG = "NotifGroupManager";
+ private static final boolean DEBUG = StatusBar.DEBUG;
+ private static final boolean SPEW = StatusBar.SPEW;
+ /**
+ * The maximum amount of time (in ms) between the posting of notifications that can be
+ * considered part of the same update batch.
+ */
+ private static final long POST_BATCH_MAX_AGE = 5000;
private final HashMap<String, NotificationGroup> mGroupMap = new HashMap<>();
private final ArraySet<OnGroupExpansionChangeListener> mExpansionChangeListeners =
new ArraySet<>();
private final ArraySet<OnGroupChangeListener> mGroupChangeListeners = new ArraySet<>();
private final Lazy<PeopleNotificationIdentifier> mPeopleNotificationIdentifier;
private final Optional<Bubbles> mBubblesOptional;
+ private final EventBuffer mEventBuffer = new EventBuffer();
private int mBarState = -1;
private HashMap<String, StatusBarNotification> mIsolatedEntries = new HashMap<>();
private HeadsUpManager mHeadsUpManager;
@@ -134,8 +147,14 @@
* When we want to remove an entry from being tracked for grouping
*/
public void onEntryRemoved(NotificationEntry removed) {
+ if (SPEW) {
+ Log.d(TAG, "onEntryRemoved: entry=" + removed);
+ }
onEntryRemovedInternal(removed, removed.getSbn());
- mIsolatedEntries.remove(removed.getKey());
+ StatusBarNotification oldSbn = mIsolatedEntries.remove(removed.getKey());
+ if (oldSbn != null) {
+ updateSuppression(mGroupMap.get(oldSbn.getGroupKey()));
+ }
}
/**
@@ -162,6 +181,9 @@
// the close future. See b/23676310 for reference.
return;
}
+ if (SPEW) {
+ Log.d(TAG, "onEntryRemovedInternal: entry=" + removed + " group=" + group.groupKey);
+ }
if (isGroupChild(removed.getKey(), isGroup, isGroupSummary)) {
group.children.remove(removed.getKey());
} else {
@@ -182,6 +204,9 @@
* Notify the group manager that a new entry was added
*/
public void onEntryAdded(final NotificationEntry added) {
+ if (SPEW) {
+ Log.d(TAG, "onEntryAdded: entry=" + added);
+ }
updateIsolation(added);
onEntryAddedInternal(added);
}
@@ -195,13 +220,16 @@
String groupKey = getGroupKey(sbn);
NotificationGroup group = mGroupMap.get(groupKey);
if (group == null) {
- group = new NotificationGroup();
+ group = new NotificationGroup(groupKey);
mGroupMap.put(groupKey, group);
for (OnGroupChangeListener listener : mGroupChangeListeners) {
listener.onGroupCreated(group, groupKey);
}
}
+ if (SPEW) {
+ Log.d(TAG, "onEntryAddedInternal: entry=" + added + " group=" + group.groupKey);
+ }
if (isGroupChild) {
NotificationEntry existing = group.children.get(added.getKey());
if (existing != null && existing != added) {
@@ -213,9 +241,11 @@
+ " added removed" + added.isRowRemoved(), new Throwable());
}
group.children.put(added.getKey(), added);
+ addToPostBatchHistory(group, added);
updateSuppression(group);
} else {
group.summary = added;
+ addToPostBatchHistory(group, added);
group.expanded = added.areChildrenExpanded();
updateSuppression(group);
if (!group.children.isEmpty()) {
@@ -231,6 +261,27 @@
}
}
+ private void addToPostBatchHistory(NotificationGroup group, @Nullable NotificationEntry entry) {
+ if (entry == null) {
+ return;
+ }
+ boolean didAdd = group.postBatchHistory.add(new PostRecord(entry));
+ if (didAdd) {
+ trimPostBatchHistory(group.postBatchHistory);
+ }
+ }
+
+ /** remove all history that's too old to be in the batch. */
+ private void trimPostBatchHistory(@NonNull TreeSet<PostRecord> postBatchHistory) {
+ if (postBatchHistory.size() <= 1) {
+ return;
+ }
+ long batchStartTime = postBatchHistory.last().postTime - POST_BATCH_MAX_AGE;
+ while (!postBatchHistory.isEmpty() && postBatchHistory.first().postTime < batchStartTime) {
+ postBatchHistory.pollFirst();
+ }
+ }
+
private void onEntryBecomingChild(NotificationEntry entry) {
updateIsolation(entry);
}
@@ -239,6 +290,9 @@
if (group == null) {
return;
}
+ NotificationEntry prevAlertOverride = group.alertOverride;
+ group.alertOverride = getPriorityConversationAlertOverride(group);
+
int childCount = 0;
boolean hasBubbles = false;
for (NotificationEntry entry : group.children.values()) {
@@ -255,18 +309,148 @@
group.suppressed = group.summary != null && !group.expanded
&& (childCount == 1
|| (childCount == 0
- && group.summary.getSbn().getNotification().isGroupSummary()
- && (hasIsolatedChildren(group) || hasBubbles)));
- if (prevSuppressed != group.suppressed) {
- for (OnGroupChangeListener listener : mGroupChangeListeners) {
- if (!mIsUpdatingUnchangedGroup) {
- listener.onGroupSuppressionChanged(group, group.suppressed);
- listener.onGroupsChanged();
+ && group.summary.getSbn().getNotification().isGroupSummary()
+ && (hasIsolatedChildren(group) || hasBubbles)));
+
+ boolean alertOverrideChanged = prevAlertOverride != group.alertOverride;
+ boolean suppressionChanged = prevSuppressed != group.suppressed;
+ if (alertOverrideChanged || suppressionChanged) {
+ if (DEBUG && alertOverrideChanged) {
+ Log.d(TAG, group + " alertOverride was=" + prevAlertOverride + " now="
+ + group.alertOverride);
+ }
+ if (DEBUG && suppressionChanged) {
+ Log.d(TAG, group + " suppressed changed to " + group.suppressed);
+ }
+ if (!mIsUpdatingUnchangedGroup) {
+ if (alertOverrideChanged) {
+ mEventBuffer.notifyAlertOverrideChanged(group, prevAlertOverride);
+ }
+ if (suppressionChanged) {
+ for (OnGroupChangeListener listener : mGroupChangeListeners) {
+ listener.onGroupSuppressionChanged(group, group.suppressed);
+ }
+ }
+ mEventBuffer.notifyGroupsChanged();
+ } else {
+ if (DEBUG) {
+ Log.d(TAG, group + " did not notify listeners of above change(s)");
}
}
}
}
+ /**
+ * Finds the isolated logical child of this group which is should be alerted instead.
+ *
+ * Notifications from priority conversations are isolated from their groups to make them more
+ * prominent, however apps may post these with a GroupAlertBehavior that has the group receiving
+ * the alert. This would lead to the group alerting even though the conversation that was
+ * updated was not actually a part of that group. This method finds the best priority
+ * conversation in this situation, if there is one, so they can be set as the alertOverride of
+ * the group.
+ *
+ * @param group the group to check
+ * @return the entry which should receive the alert instead of the group, if any.
+ */
+ @Nullable
+ private NotificationEntry getPriorityConversationAlertOverride(NotificationGroup group) {
+ // GOAL: if there is a priority child which wouldn't alert based on its groupAlertBehavior,
+ // but which should be alerting (because priority conversations are isolated), find it.
+ if (group == null || group.summary == null) {
+ if (SPEW) {
+ Log.d(TAG, "getPriorityConversationAlertOverride: null group or summary");
+ }
+ return null;
+ }
+ if (isIsolated(group.summary.getKey())) {
+ if (SPEW) {
+ Log.d(TAG, "getPriorityConversationAlertOverride: isolated group");
+ }
+ return null;
+ }
+
+ // Precondiions:
+ // * Only necessary when all notifications in the group use GROUP_ALERT_SUMMARY
+ // * Only necessary when at least one notification in the group is on a priority channel
+ if (group.summary.getSbn().getNotification().getGroupAlertBehavior()
+ != Notification.GROUP_ALERT_SUMMARY) {
+ if (SPEW) {
+ Log.d(TAG, "getPriorityConversationAlertOverride: summary != GROUP_ALERT_SUMMARY");
+ }
+ return null;
+ }
+
+ // Get the important children first, copy the keys for the final importance check,
+ // then add the non-isolated children to the map for unified lookup.
+ HashMap<String, NotificationEntry> children = getImportantConversations(group);
+ if (children == null || children.isEmpty()) {
+ if (SPEW) {
+ Log.d(TAG, "getPriorityConversationAlertOverride: no important conversations");
+ }
+ return null;
+ }
+ HashSet<String> importantChildKeys = new HashSet<>(children.keySet());
+ children.putAll(group.children);
+
+ // Ensure all children have GROUP_ALERT_SUMMARY
+ for (NotificationEntry child : children.values()) {
+ if (child.getSbn().getNotification().getGroupAlertBehavior()
+ != Notification.GROUP_ALERT_SUMMARY) {
+ if (SPEW) {
+ Log.d(TAG, "getPriorityConversationAlertOverride: "
+ + "child != GROUP_ALERT_SUMMARY");
+ }
+ return null;
+ }
+ }
+
+ // Create a merged post history from all the children
+ TreeSet<PostRecord> combinedHistory = new TreeSet<>(group.postBatchHistory);
+ for (String importantChildKey : importantChildKeys) {
+ NotificationGroup importantChildGroup = mGroupMap.get(importantChildKey);
+ combinedHistory.addAll(importantChildGroup.postBatchHistory);
+ }
+ trimPostBatchHistory(combinedHistory);
+
+ // This is a streamlined implementation of the following idea:
+ // * From the subset of notifications in the latest 'batch' of updates. A batch is:
+ // * Notifs posted less than POST_BATCH_MAX_AGE before the most recently posted.
+ // * Only including notifs newer than the second-to-last post of any notification.
+ // * Find the newest child in the batch -- the with the largest 'when' value.
+ // * If the newest child is a priority conversation, set that as the override.
+ HashSet<String> batchKeys = new HashSet<>();
+ long newestChildWhen = -1;
+ NotificationEntry newestChild = null;
+ // Iterate backwards through the post history, tracking the child with the smallest sort key
+ for (PostRecord record : combinedHistory.descendingSet()) {
+ if (batchKeys.contains(record.key)) {
+ // Once you see a notification again, the batch has ended
+ break;
+ }
+ batchKeys.add(record.key);
+ NotificationEntry child = children.get(record.key);
+ if (child != null) {
+ long childWhen = child.getSbn().getNotification().when;
+ if (newestChild == null || childWhen > newestChildWhen) {
+ newestChildWhen = childWhen;
+ newestChild = child;
+ }
+ }
+ }
+ if (newestChild != null && importantChildKeys.contains(newestChild.getKey())) {
+ if (SPEW) {
+ Log.d(TAG, "getPriorityConversationAlertOverride: result=" + newestChild);
+ }
+ return newestChild;
+ }
+ if (SPEW) {
+ Log.d(TAG, "getPriorityConversationAlertOverride: result=null, newestChild="
+ + newestChild);
+ }
+ return null;
+ }
+
private boolean hasIsolatedChildren(NotificationGroup group) {
return getNumberOfIsolatedChildren(group.summary.getSbn().getGroupKey()) != 0;
}
@@ -281,12 +465,33 @@
return count;
}
+ @Nullable
+ private HashMap<String, NotificationEntry> getImportantConversations(NotificationGroup group) {
+ String groupKey = group.summary.getSbn().getGroupKey();
+ HashMap<String, NotificationEntry> result = null;
+ for (StatusBarNotification sbn : mIsolatedEntries.values()) {
+ if (sbn.getGroupKey().equals(groupKey)) {
+ NotificationEntry entry = mGroupMap.get(sbn.getKey()).summary;
+ if (isImportantConversation(entry)) {
+ if (result == null) {
+ result = new HashMap<>();
+ }
+ result.put(sbn.getKey(), entry);
+ }
+ }
+ }
+ return result;
+ }
+
/**
* Update an entry's group information
* @param entry notification entry to update
* @param oldNotification previous notification info before this update
*/
public void onEntryUpdated(NotificationEntry entry, StatusBarNotification oldNotification) {
+ if (SPEW) {
+ Log.d(TAG, "onEntryUpdated: entry=" + entry);
+ }
onEntryUpdated(entry, oldNotification.getGroupKey(), oldNotification.isGroup(),
oldNotification.getNotification().isGroupSummary());
}
@@ -325,7 +530,17 @@
* Whether the given notification is the summary of a group that is being suppressed
*/
public boolean isSummaryOfSuppressedGroup(StatusBarNotification sbn) {
- return isGroupSuppressed(getGroupKey(sbn)) && sbn.getNotification().isGroupSummary();
+ return sbn.getNotification().isGroupSummary() && isGroupSuppressed(getGroupKey(sbn));
+ }
+
+ /**
+ * If the given notification is a summary, get the group for it.
+ */
+ public NotificationGroup getGroupForSummary(StatusBarNotification sbn) {
+ if (sbn.getNotification().isGroupSummary()) {
+ return mGroupMap.get(getGroupKey(sbn));
+ }
+ return null;
}
private boolean isOnlyChild(StatusBarNotification sbn) {
@@ -545,9 +760,7 @@
if (!sbn.isGroup() || sbn.getNotification().isGroupSummary()) {
return false;
}
- int peopleNotificationType =
- mPeopleNotificationIdentifier.get().getPeopleNotificationType(entry);
- if (peopleNotificationType == PeopleNotificationIdentifier.TYPE_IMPORTANT_PERSON) {
+ if (isImportantConversation(entry)) {
return true;
}
if (mHeadsUpManager != null && !mHeadsUpManager.isAlerting(entry.getKey())) {
@@ -560,18 +773,25 @@
|| isGroupNotFullyVisible(notificationGroup));
}
+ private boolean isImportantConversation(NotificationEntry entry) {
+ int peopleNotificationType =
+ mPeopleNotificationIdentifier.get().getPeopleNotificationType(entry);
+ return peopleNotificationType == PeopleNotificationIdentifier.TYPE_IMPORTANT_PERSON;
+ }
+
/**
* Isolate a notification from its group so that it visually shows as its own group.
*
* @param entry the notification to isolate
*/
private void isolateNotification(NotificationEntry entry) {
- StatusBarNotification sbn = entry.getSbn();
-
+ if (SPEW) {
+ Log.d(TAG, "isolateNotification: entry=" + entry);
+ }
// We will be isolated now, so lets update the groups
onEntryRemovedInternal(entry, entry.getSbn());
- mIsolatedEntries.put(sbn.getKey(), sbn);
+ mIsolatedEntries.put(entry.getKey(), entry.getSbn());
onEntryAddedInternal(entry);
// We also need to update the suppression of the old group, because this call comes
@@ -588,6 +808,14 @@
* Update the isolation of an entry, splitting it from the group.
*/
public void updateIsolation(NotificationEntry entry) {
+ // We need to buffer a few events because we do isolation changes in 3 steps:
+ // removeInternal, update mIsolatedEntries, addInternal. This means that often the
+ // alertOverride will update on the removal, however processing the event in that case can
+ // cause problems because the mIsolatedEntries map is not in its final state, so the event
+ // listener may be unable to correctly determine the true state of the group. By delaying
+ // the alertOverride change until after the add phase, we can ensure that listeners only
+ // have to handle a consistent state.
+ mEventBuffer.startBuffering();
boolean isIsolated = isIsolated(entry.getSbn().getKey());
if (shouldIsolate(entry)) {
if (!isIsolated) {
@@ -596,6 +824,7 @@
} else if (isIsolated) {
stopIsolatingNotification(entry);
}
+ mEventBuffer.flushAndStopBuffering();
}
/**
@@ -604,15 +833,15 @@
* @param entry the notification to un-isolate
*/
private void stopIsolatingNotification(NotificationEntry entry) {
- StatusBarNotification sbn = entry.getSbn();
- if (isIsolated(sbn.getKey())) {
- // not isolated anymore, we need to update the groups
- onEntryRemovedInternal(entry, entry.getSbn());
- mIsolatedEntries.remove(sbn.getKey());
- onEntryAddedInternal(entry);
- for (OnGroupChangeListener listener : mGroupChangeListeners) {
- listener.onGroupsChanged();
- }
+ if (SPEW) {
+ Log.d(TAG, "stopIsolatingNotification: entry=" + entry);
+ }
+ // not isolated anymore, we need to update the groups
+ onEntryRemovedInternal(entry, entry.getSbn());
+ mIsolatedEntries.remove(entry.getKey());
+ onEntryAddedInternal(entry);
+ for (OnGroupChangeListener listener : mGroupChangeListeners) {
+ listener.onGroupsChanged();
}
}
@@ -648,33 +877,154 @@
}
/**
+ * A record of a notification being posted, containing the time of the post and the key of the
+ * notification entry. These are stored in a TreeSet by the NotificationGroup and used to
+ * calculate a batch of notifications.
+ */
+ public static class PostRecord implements Comparable<PostRecord> {
+ public final long postTime;
+ public final String key;
+
+ /** constructs a record containing the post time and key from the notification entry */
+ public PostRecord(@NonNull NotificationEntry entry) {
+ this.postTime = entry.getSbn().getPostTime();
+ this.key = entry.getKey();
+ }
+
+ @Override
+ public int compareTo(PostRecord o) {
+ int postTimeComparison = Long.compare(this.postTime, o.postTime);
+ return postTimeComparison == 0
+ ? String.CASE_INSENSITIVE_ORDER.compare(this.key, o.key)
+ : postTimeComparison;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ PostRecord that = (PostRecord) o;
+ return postTime == that.postTime && key.equals(that.key);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(postTime, key);
+ }
+ }
+
+ /**
* Represents a notification group in the notification shade.
*/
public static class NotificationGroup {
+ public final String groupKey;
public final HashMap<String, NotificationEntry> children = new HashMap<>();
+ public final TreeSet<PostRecord> postBatchHistory = new TreeSet<>();
public NotificationEntry summary;
public boolean expanded;
/**
* Is this notification group suppressed, i.e its summary is hidden
*/
public boolean suppressed;
+ /**
+ * The child (which is isolated from this group) to which the alert should be transferred,
+ * due to priority conversations.
+ */
+ public NotificationEntry alertOverride;
+
+ NotificationGroup(String groupKey) {
+ this.groupKey = groupKey;
+ }
@Override
public String toString() {
- String result = " summary:\n "
- + (summary != null ? summary.getSbn() : "null")
- + (summary != null && summary.getDebugThrowable() != null
- ? Log.getStackTraceString(summary.getDebugThrowable())
- : "");
- result += "\n children size: " + children.size();
+ StringBuilder sb = new StringBuilder();
+ sb.append(" groupKey: ").append(groupKey);
+ sb.append("\n summary:");
+ appendEntry(sb, summary);
+ sb.append("\n children size: ").append(children.size());
for (NotificationEntry child : children.values()) {
- result += "\n " + child.getSbn()
- + (child.getDebugThrowable() != null
- ? Log.getStackTraceString(child.getDebugThrowable())
- : "");
+ appendEntry(sb, child);
}
- result += "\n summary suppressed: " + suppressed;
- return result;
+ sb.append("\n alertOverride:");
+ appendEntry(sb, alertOverride);
+ sb.append("\n summary suppressed: ").append(suppressed);
+ return sb.toString();
+ }
+
+ private void appendEntry(StringBuilder sb, NotificationEntry entry) {
+ sb.append("\n ").append(entry != null ? entry.getSbn() : "null");
+ if (entry != null && entry.getDebugThrowable() != null) {
+ sb.append(Log.getStackTraceString(entry.getDebugThrowable()));
+ }
+ }
+ }
+
+ /**
+ * This class is a toggleable buffer for a subset of events of {@link OnGroupChangeListener}.
+ * When buffering, instead of notifying the listeners it will set internal state that will allow
+ * it to notify listeners of those events later
+ */
+ private class EventBuffer {
+ private final HashMap<String, NotificationEntry> mOldAlertOverrideByGroup = new HashMap<>();
+ private boolean mIsBuffering = false;
+ private boolean mDidGroupsChange = false;
+
+ void notifyAlertOverrideChanged(NotificationGroup group,
+ NotificationEntry oldAlertOverride) {
+ if (mIsBuffering) {
+ // The value in this map is the override before the event. If there is an entry
+ // already in the map, then we are effectively coalescing two events, which means
+ // we need to preserve the original initial value.
+ mOldAlertOverrideByGroup.putIfAbsent(group.groupKey, oldAlertOverride);
+ } else {
+ for (OnGroupChangeListener listener : mGroupChangeListeners) {
+ listener.onGroupAlertOverrideChanged(group, oldAlertOverride,
+ group.alertOverride);
+ }
+ }
+ }
+
+ void notifyGroupsChanged() {
+ if (mIsBuffering) {
+ mDidGroupsChange = true;
+ } else {
+ for (OnGroupChangeListener listener : mGroupChangeListeners) {
+ listener.onGroupsChanged();
+ }
+ }
+ }
+
+ void startBuffering() {
+ mIsBuffering = true;
+ }
+
+ void flushAndStopBuffering() {
+ // stop buffering so that we can call our own helpers
+ mIsBuffering = false;
+ // alert all group alert override changes for groups that were not removed
+ for (Map.Entry<String, NotificationEntry> entry : mOldAlertOverrideByGroup.entrySet()) {
+ NotificationGroup group = mGroupMap.get(entry.getKey());
+ if (group == null) {
+ // The group can be null if this alertOverride changed before the group was
+ // permanently removed, meaning that there's no guarantee that listeners will
+ // that field clear.
+ continue;
+ }
+ NotificationEntry oldAlertOverride = entry.getValue();
+ if (group.alertOverride == oldAlertOverride) {
+ // If the final alertOverride equals the initial, it means we coalesced two
+ // events which undid the change, so we can drop it entirely.
+ continue;
+ }
+ notifyAlertOverrideChanged(group, oldAlertOverride);
+ }
+ mOldAlertOverrideByGroup.clear();
+ // alert that groups changed
+ if (mDidGroupsChange) {
+ notifyGroupsChanged();
+ mDidGroupsChange = false;
+ }
}
}
@@ -714,6 +1064,18 @@
boolean suppressed) {}
/**
+ * The alert override of a group has changed.
+ *
+ * @param group the group that has changed
+ * @param oldAlertOverride the previous notification to which the group's alerts were sent
+ * @param newAlertOverride the notification to which the group's alerts should now be sent
+ */
+ default void onGroupAlertOverrideChanged(
+ NotificationGroup group,
+ @Nullable NotificationEntry oldAlertOverride,
+ @Nullable NotificationEntry newAlertOverride) {}
+
+ /**
* A group of children just received a summary notification and should therefore become
* children of it.
*
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 751573a..b816193 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
@@ -431,6 +431,7 @@
private DismissAllAnimationListener mDismissAllAnimationListener;
private NotificationRemoteInputManager mRemoteInputManager;
private ShadeController mShadeController;
+ private Runnable mOnStackYChanged;
private final DisplayMetrics mDisplayMetrics = Dependency.get(DisplayMetrics.class);
private final LockscreenGestureLogger mLockscreenGestureLogger =
@@ -1142,14 +1143,22 @@
*/
private void updateStackPosition() {
// Consider interpolating from an mExpansionStartY for use on lockscreen and AOD
- mAmbientState.setStackY(
- MathUtils.lerp(0, mTopPadding, mAmbientState.getExpansionFraction()));
+ final float stackY = MathUtils.lerp(0, mTopPadding, mAmbientState.getExpansionFraction());
+ mAmbientState.setStackY(stackY);
+ if (mOnStackYChanged != null) {
+ mOnStackYChanged.run();
+ }
+
final float shadeBottom = getHeight() - getEmptyBottomMargin();
mAmbientState.setStackEndHeight(shadeBottom - mTopPadding);
mAmbientState.setStackHeight(
MathUtils.lerp(0, shadeBottom - mTopPadding, mAmbientState.getExpansionFraction()));
}
+ void setOnStackYChanged(Runnable onStackYChanged) {
+ mOnStackYChanged = onStackYChanged;
+ }
+
/**
* Update the height of the panel.
*
@@ -4533,7 +4542,9 @@
// We still want to call the normal scrolled changed for accessibility reasons
onScrollChanged(mScrollX, ownScrollY, mScrollX, mOwnScrollY);
mOwnScrollY = ownScrollY;
+ updateChildren();
updateOnScrollChange();
+ updateStackPosition();
}
}
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 527443e..ae9467e 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
@@ -971,6 +971,10 @@
mView.setQsExpansionFraction(expansionFraction);
}
+ public void setOnStackYChanged(Runnable onStackYChanged) {
+ mView.setOnStackYChanged(onStackYChanged);
+ }
+
public float calculateAppearFractionBypass() {
return mView.calculateAppearFractionBypass();
}
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 27ee13a..7d586ba 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
@@ -151,7 +151,8 @@
private void updateClipping(StackScrollAlgorithmState algorithmState,
AmbientState ambientState) {
- float drawStart = !ambientState.isOnKeyguard() ? ambientState.getStackY() : 0;
+ float drawStart = !ambientState.isOnKeyguard()
+ ? ambientState.getStackY() - ambientState.getScrollY() : 0;
float clipStart = 0;
int childCount = algorithmState.visibleChildren.size();
boolean firstHeadsUp = true;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
index 86ef0a7..01d489f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
@@ -39,6 +39,8 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.util.HashSet;
+import java.util.Set;
import javax.inject.Inject;
@@ -62,6 +64,8 @@
private final BatteryController mBatteryController;
private final FeatureFlags mFeatureFlags;
+ private final Set<Callback> mCallbacks = new HashSet<>();
+
private boolean mDozeAlwaysOn;
private boolean mControlScreenOffAnimation;
@@ -250,9 +254,26 @@
return mResources.getBoolean(R.bool.doze_long_press_uses_prox);
}
+ /**
+ * Callback to listen for DozeParameter changes.
+ */
+ public void addCallback(Callback callback) {
+ mCallbacks.add(callback);
+ }
+
+ /**
+ * Remove callback that listens for DozeParameter changes.
+ */
+ public void removeCallback(Callback callback) {
+ mCallbacks.remove(callback);
+ }
+
@Override
public void onTuningChanged(String key, String newValue) {
mDozeAlwaysOn = mAmbientDisplayConfiguration.alwaysOnEnabled(UserHandle.USER_CURRENT);
+ for (Callback callback : mCallbacks) {
+ callback.onAlwaysOnChange();
+ }
}
@Override
@@ -270,4 +291,11 @@
pw.print("getSelectivelyRegisterSensorsUsingProx(): ");
pw.println(getSelectivelyRegisterSensorsUsingProx());
}
+
+ interface Callback {
+ /**
+ * Invoked when the value of getAlwaysOn may have changed.
+ */
+ void onAlwaysOnChange();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
index 3827123f..4b545eb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
@@ -301,7 +301,7 @@
}
///////////////////////////////////////////////////////////////////////////////////////////////
- // HeadsUpManager public methods overrides:
+ // HeadsUpManager public methods overrides and overloads:
@Override
public boolean isTrackingHeadsUp() {
@@ -318,6 +318,18 @@
mSwipedOutKeys.add(key);
}
+ public boolean removeNotification(@NonNull String key, boolean releaseImmediately,
+ boolean animate) {
+ if (animate) {
+ return removeNotification(key, releaseImmediately);
+ } else {
+ mAnimationStateHandler.setHeadsUpGoingAwayAnimationsAllowed(false);
+ boolean removed = removeNotification(key, releaseImmediately);
+ mAnimationStateHandler.setHeadsUpGoingAwayAnimationsAllowed(true);
+ return removed;
+ }
+ }
+
///////////////////////////////////////////////////////////////////////////////////////////////
// Dumpable overrides:
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 cabfbca..71ba091 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -935,7 +935,7 @@
private void onWalletClick(View v) {
// More coming here; need to inform the user about how to proceed
- if (!mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
+ if (mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
return;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java
index 3181f52..9787a944 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java
@@ -22,12 +22,12 @@
import android.os.SystemClock;
import android.service.notification.StatusBarNotification;
import android.util.ArrayMap;
+import android.util.Log;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.systemui.Dependency;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
-import com.android.systemui.statusbar.AlertingNotificationManager;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -41,17 +41,21 @@
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
import java.util.ArrayList;
+import java.util.List;
import java.util.Objects;
/**
* A helper class dealing with the alert interactions between {@link NotificationGroupManagerLegacy}
* and {@link HeadsUpManager}. In particular, this class deals with keeping
- * the correct notification in a group alerting based off the group suppression.
+ * the correct notification in a group alerting based off the group suppression and alertOverride.
*/
public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedListener,
StateListener {
private static final long ALERT_TRANSFER_TIMEOUT = 300;
+ private static final String TAG = "NotifGroupAlertTransfer";
+ private static final boolean DEBUG = StatusBar.DEBUG;
+ private static final boolean SPEW = StatusBar.SPEW;
/**
* The list of entries containing group alert metadata for each group. Keyed by group key.
@@ -142,41 +146,98 @@
@Override
public void onGroupSuppressionChanged(NotificationGroup group, boolean suppressed) {
- if (suppressed) {
- if (mHeadsUpManager.isAlerting(group.summary.getKey())) {
- handleSuppressedSummaryAlerted(group.summary, mHeadsUpManager);
- }
- } else {
- // Group summary can be null if we are no longer suppressed because the summary was
- // removed. In that case, we don't need to alert the summary.
- if (group.summary == null) {
- return;
- }
- GroupAlertEntry groupAlertEntry = mGroupAlertEntries.get(mGroupManager.getGroupKey(
- group.summary.getSbn()));
- // Group is no longer suppressed. We should check if we need to transfer the alert
- // back to the summary now that it's no longer suppressed.
- if (groupAlertEntry.mAlertSummaryOnNextAddition) {
- if (!mHeadsUpManager.isAlerting(group.summary.getKey())) {
- alertNotificationWhenPossible(group.summary, mHeadsUpManager);
- }
- groupAlertEntry.mAlertSummaryOnNextAddition = false;
- } else {
- checkShouldTransferBack(groupAlertEntry);
- }
+ if (DEBUG) {
+ Log.d(TAG, "!! onGroupSuppressionChanged: group.summary=" + group.summary
+ + " suppressed=" + suppressed);
}
+ NotificationEntry oldAlertOverride = group.alertOverride;
+ onGroupChanged(group, oldAlertOverride);
+ }
+
+ @Override
+ public void onGroupAlertOverrideChanged(NotificationGroup group,
+ @Nullable NotificationEntry oldAlertOverride,
+ @Nullable NotificationEntry newAlertOverride) {
+ if (DEBUG) {
+ Log.d(TAG, "!! onGroupAlertOverrideChanged: group.summary=" + group.summary
+ + " oldAlertOverride=" + oldAlertOverride
+ + " newAlertOverride=" + newAlertOverride);
+ }
+ onGroupChanged(group, oldAlertOverride);
}
};
- @Override
- public void onHeadsUpStateChanged(NotificationEntry entry, boolean isHeadsUp) {
- onAlertStateChanged(entry, isHeadsUp, mHeadsUpManager);
+ /**
+ * Called when either the suppressed or alertOverride fields of the group changed
+ *
+ * @param group the group which changed
+ * @param oldAlertOverride the previous value of group.alertOverride
+ */
+ private void onGroupChanged(NotificationGroup group,
+ NotificationEntry oldAlertOverride) {
+ // Group summary can be null if we are no longer suppressed because the summary was
+ // removed. In that case, we don't need to alert the summary.
+ if (group.summary == null) {
+ if (DEBUG) {
+ Log.d(TAG, "onGroupChanged: summary is null");
+ }
+ return;
+ }
+ if (group.suppressed || group.alertOverride != null) {
+ checkForForwardAlertTransfer(group.summary, oldAlertOverride);
+ } else {
+ if (DEBUG) {
+ Log.d(TAG, "onGroupChanged: maybe transfer back");
+ }
+ GroupAlertEntry groupAlertEntry = mGroupAlertEntries.get(mGroupManager.getGroupKey(
+ group.summary.getSbn()));
+ // Group is no longer suppressed or overridden.
+ // We should check if we need to transfer the alert back to the summary.
+ if (groupAlertEntry.mAlertSummaryOnNextAddition) {
+ if (!mHeadsUpManager.isAlerting(group.summary.getKey())) {
+ alertNotificationWhenPossible(group.summary);
+ }
+ groupAlertEntry.mAlertSummaryOnNextAddition = false;
+ } else {
+ checkShouldTransferBack(groupAlertEntry);
+ }
+ }
}
- private void onAlertStateChanged(NotificationEntry entry, boolean isAlerting,
- AlertingNotificationManager alertManager) {
- if (isAlerting && mGroupManager.isSummaryOfSuppressedGroup(entry.getSbn())) {
- handleSuppressedSummaryAlerted(entry, alertManager);
+ @Override
+ public void onHeadsUpStateChanged(NotificationEntry entry, boolean isHeadsUp) {
+ if (DEBUG) {
+ Log.d(TAG, "!! onHeadsUpStateChanged: entry=" + entry + " isHeadsUp=" + isHeadsUp);
+ }
+ if (isHeadsUp && entry.getSbn().getNotification().isGroupSummary()) {
+ // a group summary is alerting; trigger the forward transfer checks
+ checkForForwardAlertTransfer(entry, /* oldAlertOverride */ null);
+ }
+ }
+
+ /**
+ * Handles changes in a group's suppression or alertOverride, but where at least one of those
+ * conditions is still true (either the group is suppressed, the group has an alertOverride,
+ * or both). The method determined which kind of child needs to receive the alert, finds the
+ * entry currently alerting, and makes the transfer.
+ *
+ * Internally, this is handled with two main cases: the override needs the alert, or there is
+ * no override but the summary is suppressed (so an isolated child needs the alert).
+ *
+ * @param summary the notification entry of the summary of the logical group.
+ * @param oldAlertOverride the former value of group.alertOverride, before whatever event
+ * required us to check for for a transfer condition.
+ */
+ private void checkForForwardAlertTransfer(NotificationEntry summary,
+ NotificationEntry oldAlertOverride) {
+ if (DEBUG) {
+ Log.d(TAG, "checkForForwardAlertTransfer: enter");
+ }
+ NotificationGroup group = mGroupManager.getGroupForSummary(summary.getSbn());
+ if (group != null && group.alertOverride != null) {
+ handleOverriddenSummaryAlerted(summary);
+ } else if (mGroupManager.isSummaryOfSuppressedGroup(summary.getSbn())) {
+ handleSuppressedSummaryAlerted(summary, oldAlertOverride);
}
}
@@ -186,9 +247,16 @@
// see as early as we can if we need to abort a transfer.
@Override
public void onPendingEntryAdded(NotificationEntry entry) {
+ if (DEBUG) {
+ Log.d(TAG, "!! onPendingEntryAdded: entry=" + entry);
+ }
String groupKey = mGroupManager.getGroupKey(entry.getSbn());
GroupAlertEntry groupAlertEntry = mGroupAlertEntries.get(groupKey);
- if (groupAlertEntry != null) {
+ if (groupAlertEntry != null && groupAlertEntry.mGroup.alertOverride == null) {
+ // new pending group entries require us to transfer back from the child to the
+ // group, but alertOverrides are only present in very limited circumstances, so
+ // while it's possible the group should ALSO alert, the previous detection which set
+ // this alertOverride won't be invalidated by this notification added to this group.
checkShouldTransferBack(groupAlertEntry);
}
}
@@ -262,43 +330,128 @@
}
/**
- * Handles the scenario where a summary that has been suppressed is alerted. A suppressed
+ * Handles the scenario where a summary that has been suppressed is itself, or has a former
+ * alertOverride (in the form of an isolated logical child) which was alerted. A suppressed
* summary should for all intents and purposes be invisible to the user and as a result should
* not alert. When this is the case, it is our responsibility to pass the alert to the
* appropriate child which will be the representative notification alerting for the group.
*
- * @param summary the summary that is suppressed and alerting
- * @param alertManager the alert manager that manages the alerting summary
+ * @param summary the summary that is suppressed and (potentially) alerting
+ * @param oldAlertOverride the alertOverride before whatever event triggered this method. If
+ * the alert override was removed, this will be the entry that should
+ * be transferred back from.
*/
private void handleSuppressedSummaryAlerted(@NonNull NotificationEntry summary,
- @NonNull AlertingNotificationManager alertManager) {
- StatusBarNotification sbn = summary.getSbn();
+ NotificationEntry oldAlertOverride) {
+ if (DEBUG) {
+ Log.d(TAG, "handleSuppressedSummaryAlerted: summary=" + summary);
+ }
GroupAlertEntry groupAlertEntry =
- mGroupAlertEntries.get(mGroupManager.getGroupKey(sbn));
+ mGroupAlertEntries.get(mGroupManager.getGroupKey(summary.getSbn()));
+
if (!mGroupManager.isSummaryOfSuppressedGroup(summary.getSbn())
- || !alertManager.isAlerting(sbn.getKey())
|| groupAlertEntry == null) {
+ if (DEBUG) {
+ Log.d(TAG, "handleSuppressedSummaryAlerted: invalid state");
+ }
+ return;
+ }
+ boolean summaryIsAlerting = mHeadsUpManager.isAlerting(summary.getKey());
+ boolean priorityIsAlerting = oldAlertOverride != null
+ && mHeadsUpManager.isAlerting(oldAlertOverride.getKey());
+ if (!summaryIsAlerting && !priorityIsAlerting) {
+ if (DEBUG) {
+ Log.d(TAG, "handleSuppressedSummaryAlerted: no summary or override alerting");
+ }
return;
}
if (pendingInflationsWillAddChildren(groupAlertEntry.mGroup)) {
// New children will actually be added to this group, let's not transfer the alert.
+ if (DEBUG) {
+ Log.d(TAG, "handleSuppressedSummaryAlerted: pending inflations");
+ }
return;
}
NotificationEntry child =
mGroupManager.getLogicalChildren(summary.getSbn()).iterator().next();
- if (child != null) {
- if (child.getRow().keepInParent()
- || child.isRowRemoved()
- || child.isRowDismissed()) {
- // The notification is actually already removed. No need to alert it.
- return;
+ if (summaryIsAlerting) {
+ if (DEBUG) {
+ Log.d(TAG, "handleSuppressedSummaryAlerted: transfer summary -> child");
}
- if (!alertManager.isAlerting(child.getKey()) && onlySummaryAlerts(summary)) {
- groupAlertEntry.mLastAlertTransferTime = SystemClock.elapsedRealtime();
+ tryTransferAlertState(summary, /*from*/ summary, /*to*/ child, groupAlertEntry);
+ return;
+ }
+ // Summary didn't have the alert, so we're in "transfer back" territory. First, make sure
+ // it's not too late to transfer back, then transfer the alert from the oldAlertOverride to
+ // the isolated child which should receive the alert.
+ if (!canStillTransferBack(groupAlertEntry)) {
+ if (DEBUG) {
+ Log.d(TAG, "handleSuppressedSummaryAlerted: transfer from override: too late");
}
- transferAlertState(summary, child, alertManager);
+ return;
+ }
+
+ if (DEBUG) {
+ Log.d(TAG, "handleSuppressedSummaryAlerted: transfer override -> child");
+ }
+ tryTransferAlertState(summary, /*from*/ oldAlertOverride, /*to*/ child, groupAlertEntry);
+ }
+
+ /**
+ * Checks for and handles the scenario where the given entry is the summary of a group which
+ * has an alertOverride, and either the summary itself or one of its logical isolated children
+ * is currently alerting (which happens if the summary is suppressed).
+ */
+ private void handleOverriddenSummaryAlerted(NotificationEntry summary) {
+ if (DEBUG) {
+ Log.d(TAG, "handleOverriddenSummaryAlerted: summary=" + summary);
+ }
+ GroupAlertEntry groupAlertEntry =
+ mGroupAlertEntries.get(mGroupManager.getGroupKey(summary.getSbn()));
+ NotificationGroup group = mGroupManager.getGroupForSummary(summary.getSbn());
+ if (group == null || group.alertOverride == null || groupAlertEntry == null) {
+ if (DEBUG) {
+ Log.d(TAG, "handleOverriddenSummaryAlerted: invalid state");
+ }
+ return;
+ }
+ boolean summaryIsAlerting = mHeadsUpManager.isAlerting(summary.getKey());
+ if (summaryIsAlerting) {
+ if (DEBUG) {
+ Log.d(TAG, "handleOverriddenSummaryAlerted: transfer summary -> override");
+ }
+ tryTransferAlertState(summary, /*from*/ summary, group.alertOverride, groupAlertEntry);
+ return;
+ }
+ // Summary didn't have the alert, so we're in "transfer back" territory. First, make sure
+ // it's not too late to transfer back, then remove the alert from any of the logical
+ // children, and if one of them was alerting, we can alert the override.
+ if (!canStillTransferBack(groupAlertEntry)) {
+ if (DEBUG) {
+ Log.d(TAG, "handleOverriddenSummaryAlerted: transfer from child: too late");
+ }
+ return;
+ }
+ List<NotificationEntry> children = mGroupManager.getLogicalChildren(summary.getSbn());
+ if (children == null) {
+ if (DEBUG) {
+ Log.d(TAG, "handleOverriddenSummaryAlerted: no children");
+ }
+ return;
+ }
+ children.remove(group.alertOverride); // do not release the alert on our desired destination
+ boolean releasedChild = releaseChildAlerts(children);
+ if (releasedChild) {
+ if (DEBUG) {
+ Log.d(TAG, "handleOverriddenSummaryAlerted: transfer child -> override");
+ }
+ tryTransferAlertState(summary, /*from*/ null, group.alertOverride, groupAlertEntry);
+ } else {
+ if (DEBUG) {
+ Log.d(TAG, "handleOverriddenSummaryAlerted: no child alert released");
+ }
}
}
@@ -307,14 +460,37 @@
* immediately to have the incorrect one up as short as possible. The second should alert
* when possible.
*
+ * @param summary entry of the summary
* @param fromEntry entry to transfer alert from
* @param toEntry entry to transfer to
- * @param alertManager alert manager for the alert type
*/
- private void transferAlertState(@NonNull NotificationEntry fromEntry, @NonNull NotificationEntry toEntry,
- @NonNull AlertingNotificationManager alertManager) {
- alertManager.removeNotification(fromEntry.getKey(), true /* releaseImmediately */);
- alertNotificationWhenPossible(toEntry, alertManager);
+ private void tryTransferAlertState(
+ NotificationEntry summary,
+ NotificationEntry fromEntry,
+ NotificationEntry toEntry,
+ GroupAlertEntry groupAlertEntry) {
+ if (toEntry != null) {
+ if (toEntry.getRow().keepInParent()
+ || toEntry.isRowRemoved()
+ || toEntry.isRowDismissed()) {
+ // The notification is actually already removed. No need to alert it.
+ return;
+ }
+ if (!mHeadsUpManager.isAlerting(toEntry.getKey()) && onlySummaryAlerts(summary)) {
+ groupAlertEntry.mLastAlertTransferTime = SystemClock.elapsedRealtime();
+ }
+ if (DEBUG) {
+ Log.d(TAG, "transferAlertState: fromEntry=" + fromEntry + " toEntry=" + toEntry);
+ }
+ transferAlertState(fromEntry, toEntry);
+ }
+ }
+ private void transferAlertState(@Nullable NotificationEntry fromEntry,
+ @NonNull NotificationEntry toEntry) {
+ if (fromEntry != null) {
+ mHeadsUpManager.removeNotification(fromEntry.getKey(), true /* releaseImmediately */);
+ }
+ alertNotificationWhenPossible(toEntry);
}
/**
@@ -326,11 +502,13 @@
* more children are coming. Thus, if a child is added within a certain timeframe after we
* transfer, we back out and alert the summary again.
*
+ * An alert can only transfer back within a small window of time after a transfer away from the
+ * summary to a child happened.
+ *
* @param groupAlertEntry group alert entry to check
*/
private void checkShouldTransferBack(@NonNull GroupAlertEntry groupAlertEntry) {
- if (SystemClock.elapsedRealtime() - groupAlertEntry.mLastAlertTransferTime
- < ALERT_TRANSFER_TIMEOUT) {
+ if (canStillTransferBack(groupAlertEntry)) {
NotificationEntry summary = groupAlertEntry.mGroup.summary;
if (!onlySummaryAlerts(summary)) {
@@ -338,30 +516,17 @@
}
ArrayList<NotificationEntry> children = mGroupManager.getLogicalChildren(
summary.getSbn());
- int numChildren = children.size();
+ int numActiveChildren = children.size();
int numPendingChildren = getPendingChildrenNotAlerting(groupAlertEntry.mGroup);
- numChildren += numPendingChildren;
+ int numChildren = numActiveChildren + numPendingChildren;
if (numChildren <= 1) {
return;
}
- boolean releasedChild = false;
- for (int i = 0; i < children.size(); i++) {
- NotificationEntry entry = children.get(i);
- if (onlySummaryAlerts(entry) && mHeadsUpManager.isAlerting(entry.getKey())) {
- releasedChild = true;
- mHeadsUpManager.removeNotification(
- entry.getKey(), true /* releaseImmediately */);
- }
- if (mPendingAlerts.containsKey(entry.getKey())) {
- // This is the child that would've been removed if it was inflated.
- releasedChild = true;
- mPendingAlerts.get(entry.getKey()).mAbortOnInflation = true;
- }
- }
+ boolean releasedChild = releaseChildAlerts(children);
if (releasedChild && !mHeadsUpManager.isAlerting(summary.getKey())) {
- boolean notifyImmediately = (numChildren - numPendingChildren) > 1;
+ boolean notifyImmediately = numActiveChildren > 1;
if (notifyImmediately) {
- alertNotificationWhenPossible(summary, mHeadsUpManager);
+ alertNotificationWhenPossible(summary);
} else {
// Should wait until the pending child inflates before alerting.
groupAlertEntry.mAlertSummaryOnNextAddition = true;
@@ -371,25 +536,61 @@
}
}
+ private boolean canStillTransferBack(@NonNull GroupAlertEntry groupAlertEntry) {
+ return SystemClock.elapsedRealtime() - groupAlertEntry.mLastAlertTransferTime
+ < ALERT_TRANSFER_TIMEOUT;
+ }
+
+ private boolean releaseChildAlerts(List<NotificationEntry> children) {
+ boolean releasedChild = false;
+ if (SPEW) {
+ Log.d(TAG, "releaseChildAlerts: numChildren=" + children.size());
+ }
+ for (int i = 0; i < children.size(); i++) {
+ NotificationEntry entry = children.get(i);
+ if (SPEW) {
+ Log.d(TAG, "releaseChildAlerts: checking i=" + i + " entry=" + entry
+ + " onlySummaryAlerts=" + onlySummaryAlerts(entry)
+ + " isAlerting=" + mHeadsUpManager.isAlerting(entry.getKey())
+ + " isPendingAlert=" + mPendingAlerts.containsKey(entry.getKey()));
+ }
+ if (onlySummaryAlerts(entry) && mHeadsUpManager.isAlerting(entry.getKey())) {
+ releasedChild = true;
+ mHeadsUpManager.removeNotification(
+ entry.getKey(), true /* releaseImmediately */);
+ }
+ if (mPendingAlerts.containsKey(entry.getKey())) {
+ // This is the child that would've been removed if it was inflated.
+ releasedChild = true;
+ mPendingAlerts.get(entry.getKey()).mAbortOnInflation = true;
+ }
+ }
+ if (SPEW) {
+ Log.d(TAG, "releaseChildAlerts: didRelease=" + releasedChild);
+ }
+ return releasedChild;
+ }
+
/**
* Tries to alert the notification. If its content view is not inflated, we inflate and continue
* when the entry finishes inflating the view.
*
* @param entry entry to show
- * @param alertManager alert manager for the alert type
*/
- private void alertNotificationWhenPossible(@NonNull NotificationEntry entry,
- @NonNull AlertingNotificationManager alertManager) {
- @InflationFlag int contentFlag = alertManager.getContentFlag();
+ private void alertNotificationWhenPossible(@NonNull NotificationEntry entry) {
+ @InflationFlag int contentFlag = mHeadsUpManager.getContentFlag();
final RowContentBindParams params = mRowContentBindStage.getStageParams(entry);
if ((params.getContentViews() & contentFlag) == 0) {
+ if (DEBUG) {
+ Log.d(TAG, "alertNotificationWhenPossible: async requestRebind entry=" + entry);
+ }
mPendingAlerts.put(entry.getKey(), new PendingAlertInfo(entry));
params.requireContentViews(contentFlag);
mRowContentBindStage.requestRebind(entry, en -> {
PendingAlertInfo alertInfo = mPendingAlerts.remove(entry.getKey());
if (alertInfo != null) {
if (alertInfo.isStillValid()) {
- alertNotificationWhenPossible(entry, mHeadsUpManager);
+ alertNotificationWhenPossible(entry);
} else {
// The transfer is no longer valid. Free the content.
mRowContentBindStage.getStageParams(entry).markContentViewsFreeable(
@@ -400,10 +601,16 @@
});
return;
}
- if (alertManager.isAlerting(entry.getKey())) {
- alertManager.updateNotification(entry.getKey(), true /* alert */);
+ if (mHeadsUpManager.isAlerting(entry.getKey())) {
+ if (DEBUG) {
+ Log.d(TAG, "alertNotificationWhenPossible: continue alerting entry=" + entry);
+ }
+ mHeadsUpManager.updateNotification(entry.getKey(), true /* alert */);
} else {
- alertManager.showNotification(entry);
+ if (DEBUG) {
+ Log.d(TAG, "alertNotificationWhenPossible: start alerting entry=" + entry);
+ }
+ mHeadsUpManager.showNotification(entry);
}
}
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 83a64f1..c79e503 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -525,6 +525,7 @@
private NotificationShelfController mNotificationShelfController;
private int mScrimCornerRadius;
private int mScreenCornerRadius;
+ private int mNotificationScrimPadding;
private final QuickAccessWalletClient mQuickAccessWalletClient;
private final Executor mUiExecutor;
@@ -812,6 +813,8 @@
R.dimen.notification_scrim_corner_radius);
mScreenCornerRadius = mResources.getDimensionPixelSize(
com.android.internal.R.dimen.rounded_corner_radius);
+ mNotificationScrimPadding = mResources.getDimensionPixelSize(
+ R.dimen.notification_side_paddings);
}
private void updateViewControllers(KeyguardStatusView keyguardStatusView,
@@ -2043,29 +2046,37 @@
mMediaHierarchyManager.setQsExpansion(qsExpansionFraction);
int qsPanelBottomY = calculateQsBottomPosition(qsExpansionFraction);
mScrimController.setQsPosition(qsExpansionFraction, qsPanelBottomY);
- setNotificationBounds(qsExpansionFraction, qsPanelBottomY);
mNotificationStackScrollLayoutController.setQsExpansionFraction(qsExpansionFraction);
mDepthController.setQsPanelExpansion(qsExpansionFraction);
}
+ private Runnable mOnStackYChanged = () -> {
+ if (mQs != null) {
+ setNotificationBounds();
+ }
+ };
+
/**
* Updates scrim bounds, QS clipping, and KSV clipping as well based on the bounds of the shade
* and QS state.
- *
- * @param qsFraction QS expansion fraction, from getQsExpansionFraction().
- * @param qsPanelBottomY Absolute y position of the bottom of QS as it's being pulled.
*/
- private void setNotificationBounds(float qsFraction, int qsPanelBottomY) {
+ private void setNotificationBounds() {
int top = 0;
int bottom = 0;
int left = 0;
int right = 0;
- boolean visible = (qsFraction > 0 || qsPanelBottomY > 0)
+
+ final int qsPanelBottomY = calculateQsBottomPosition(getQsExpansionFraction());
+ final boolean visible = (getQsExpansionFraction() > 0 || qsPanelBottomY > 0)
&& !mShouldUseSplitNotificationShade;
+ final float notificationTop = mAmbientState.getStackY()
+ - mNotificationScrimPadding
+ - mAmbientState.getScrollY();
+ setQsExpansionEnabled(mAmbientState.getScrollY() == 0);
+
int radius = mScrimCornerRadius;
if (visible || !mShouldUseSplitNotificationShade) {
if (!mShouldUseSplitNotificationShade) {
- float notificationTop = mAmbientState.getStackY() - mQsNotificationTopPadding;
top = (int) Math.min(qsPanelBottomY, notificationTop);
bottom = getView().getBottom();
left = getView().getLeft();
@@ -2245,6 +2256,7 @@
break;
case FLING_HIDE:
default:
+ mQs.closeDetail();
target = 0;
}
if (target == mQsExpansionHeight) {
@@ -3060,6 +3072,7 @@
// The expandedHeight is always the full panel Height when bypassing
expandedHeight = getMaxPanelHeightNonBypass();
}
+ mNotificationStackScrollLayoutController.setOnStackYChanged(mOnStackYChanged);
mNotificationStackScrollLayoutController.setExpandedHeight(expandedHeight);
updateKeyguardBottomAreaAlpha();
updateBigClockAlpha();
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 6fb18d4..c092931 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -49,7 +49,6 @@
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dock.DockManager;
import com.android.systemui.scrim.ScrimView;
-import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.notification.stack.ViewState;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -211,10 +210,9 @@
AlarmManager alarmManager, KeyguardStateController keyguardStateController,
DelayedWakeLock.Builder delayedWakeLockBuilder, Handler handler,
KeyguardUpdateMonitor keyguardUpdateMonitor, DockManager dockManager,
- ConfigurationController configurationController,
- FeatureFlags featureFlags, @Main Executor mainExecutor) {
+ ConfigurationController configurationController, @Main Executor mainExecutor) {
mScrimStateListener = lightBarController::setScrimState;
- mDefaultScrimAlpha = featureFlags.isShadeOpaque() ? BUSY_SCRIM_ALPHA : GAR_SCRIM_ALPHA;
+ mDefaultScrimAlpha = BUSY_SCRIM_ALPHA;
ScrimState.BUBBLE_EXPANDED.setBubbleAlpha(BUBBLE_SCRIM_ALPHA);
mKeyguardStateController = keyguardStateController;
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 dd9ebfc..6ef4663 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -241,7 +241,6 @@
import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
import com.android.systemui.statusbar.policy.UserSwitcherController;
-import com.android.systemui.tuner.TunerService;
import com.android.systemui.volume.VolumeComponent;
import com.android.systemui.wmshell.BubblesManager;
import com.android.wm.shell.bubbles.Bubbles;
@@ -800,7 +799,6 @@
OngoingCallController ongoingCallController,
SystemStatusAnimationScheduler animationScheduler,
PrivacyDotViewController dotViewController,
- TunerService tunerService,
FeatureFlags featureFlags,
KeyguardUnlockAnimationController keyguardUnlockAnimationController) {
super(context);
@@ -886,15 +884,6 @@
mDotViewController = dotViewController;
mFeatureFlags = featureFlags;
- tunerService.addTunable(
- (key, newValue) -> {
- if (key.equals(Settings.Secure.DOZE_ALWAYS_ON)) {
- updateLightRevealScrimVisibility();
- }
- },
- Settings.Secure.DOZE_ALWAYS_ON
- );
-
mExpansionChangedListeners = new ArrayList<>();
mBubbleExpandListener =
@@ -1038,6 +1027,7 @@
mNotificationShadeWindowViewController,
mNotificationPanelViewController,
mAmbientIndicationContainer);
+ mDozeParameters.addCallback(this::updateLightRevealScrimVisibility);
mConfigurationController.addCallback(this);
@@ -1422,7 +1412,8 @@
mNotificationAnimationProvider = new NotificationLaunchAnimatorControllerProvider(
mNotificationShadeWindowViewController,
mStackScrollerController.getNotificationListContainer(),
- mNotificationShadeDepthControllerLazy.get()
+ mNotificationShadeDepthControllerLazy.get(),
+ mHeadsUpManager
);
// TODO: inject this.
@@ -2795,7 +2786,7 @@
intent, mLockscreenUserManager.getCurrentUserId());
ActivityLaunchAnimator.Controller animController = null;
- if (animationController != null && areLaunchAnimationsEnabled()) {
+ if (animationController != null) {
animController = dismissShade ? new StatusBarLaunchAnimatorController(
animationController, this, true /* isLaunchForActivity */)
: animationController;
@@ -2811,46 +2802,48 @@
intent.setFlags(
Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.addFlags(flags);
- int[] result = new int[] { ActivityManager.START_CANCELED };
+ int[] result = new int[]{ActivityManager.START_CANCELED};
- mActivityLaunchAnimator.startIntentWithAnimation(animCallbackForLambda, (adapter) -> {
- ActivityOptions options = new ActivityOptions(
- getActivityOptions(mDisplayId, adapter));
- options.setDisallowEnterPictureInPictureWhileLaunching(
- disallowEnterPictureInPictureWhileLaunching);
- if (CameraIntents.isInsecureCameraIntent(intent)) {
- // Normally an activity will set it's requested rotation
- // animation on its window. However when launching an activity
- // causes the orientation to change this is too late. In these cases
- // the default animation is used. This doesn't look good for
- // the camera (as it rotates the camera contents out of sync
- // with physical reality). So, we ask the WindowManager to
- // force the crossfade animation if an orientation change
- // happens to occur during the launch.
- options.setRotationAnimationHint(
- WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS);
- }
- if (intent.getAction() == Settings.Panel.ACTION_VOLUME) {
- // Settings Panel is implemented as activity(not a dialog), so
- // underlying app is paused and may enter picture-in-picture mode
- // as a result.
- // So we need to disable picture-in-picture mode here
- // if it is volume panel.
- options.setDisallowEnterPictureInPictureWhileLaunching(true);
- }
+ mActivityLaunchAnimator.startIntentWithAnimation(animCallbackForLambda,
+ areLaunchAnimationsEnabled(), (adapter) -> {
+ ActivityOptions options = new ActivityOptions(
+ getActivityOptions(mDisplayId, adapter));
+ options.setDisallowEnterPictureInPictureWhileLaunching(
+ disallowEnterPictureInPictureWhileLaunching);
+ if (CameraIntents.isInsecureCameraIntent(intent)) {
+ // Normally an activity will set it's requested rotation
+ // animation on its window. However when launching an activity
+ // causes the orientation to change this is too late. In these cases
+ // the default animation is used. This doesn't look good for
+ // the camera (as it rotates the camera contents out of sync
+ // with physical reality). So, we ask the WindowManager to
+ // force the crossfade animation if an orientation change
+ // happens to occur during the launch.
+ options.setRotationAnimationHint(
+ WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS);
+ }
+ if (intent.getAction() == Settings.Panel.ACTION_VOLUME) {
+ // Settings Panel is implemented as activity(not a dialog), so
+ // underlying app is paused and may enter picture-in-picture mode
+ // as a result.
+ // So we need to disable picture-in-picture mode here
+ // if it is volume panel.
+ options.setDisallowEnterPictureInPictureWhileLaunching(true);
+ }
- try {
- result[0] = ActivityTaskManager.getService().startActivityAsUser(
- null, mContext.getBasePackageName(), mContext.getAttributionTag(),
- intent,
- intent.resolveTypeIfNeeded(mContext.getContentResolver()),
- null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null,
- options.toBundle(), UserHandle.CURRENT.getIdentifier());
- } catch (RemoteException e) {
- Log.w(TAG, "Unable to start activity", e);
- }
- return result[0];
- });
+ try {
+ result[0] = ActivityTaskManager.getService().startActivityAsUser(
+ null, mContext.getBasePackageName(),
+ mContext.getAttributionTag(),
+ intent,
+ intent.resolveTypeIfNeeded(mContext.getContentResolver()),
+ null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null,
+ options.toBundle(), UserHandle.CURRENT.getIdentifier());
+ } catch (RemoteException e) {
+ Log.w(TAG, "Unable to start activity", e);
+ }
+ return result[0];
+ });
if (callback != null) {
callback.onActivityStarted(result[0]);
@@ -4569,19 +4562,17 @@
&& mActivityIntentHelper.wouldLaunchResolverActivity(intent.getIntent(),
mLockscreenUserManager.getCurrentUserId());
- boolean animate = animationController != null && areLaunchAnimationsEnabled();
- boolean collapse = !animate;
+ boolean collapse = animationController == null;
executeActionDismissingKeyguard(() -> {
try {
// We wrap animationCallback with a StatusBarLaunchAnimatorController so that the
// shade is collapsed after the animation (or when it is cancelled, aborted, etc).
ActivityLaunchAnimator.Controller controller =
- animate ? new StatusBarLaunchAnimatorController(animationController, this,
- intent.isActivity())
- : null;
+ animationController != null ? new StatusBarLaunchAnimatorController(
+ animationController, this, intent.isActivity()) : null;
mActivityLaunchAnimator.startPendingIntentWithAnimation(
- controller,
+ controller, areLaunchAnimationsEnabled(),
(animationAdapter) -> intent.sendAndReturnResult(null, 0, null, null, null,
null, getActivityOptions(mDisplayId, animationAdapter)));
} catch (PendingIntent.CanceledException e) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
index 4356b52..ab58aae6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -283,7 +283,13 @@
mLogger.logHandleClickAfterKeyguardDismissed(entry.getKey());
// TODO: Some of this code may be able to move to NotificationEntryManager.
- removeHUN(row);
+ String key = row.getEntry().getSbn().getKey();
+ if (mHeadsUpManager != null && mHeadsUpManager.isAlerting(key)) {
+ // Release the HUN notification to the shade.
+ if (mPresenter.isPresenterFullyCollapsed()) {
+ HeadsUpUtil.setIsClickedHeadsUpNotification(row, true);
+ }
+ }
final Runnable runnable = () -> handleNotificationClickAfterPanelCollapsed(
entry, row, controller, intent,
@@ -331,6 +337,7 @@
// bypass work challenge
if (mStatusBarRemoteInputCallback.startWorkChallengeIfNecessary(userId,
intent.getIntentSender(), notificationKey)) {
+ removeHUN(row);
// Show work challenge, do not run PendingIntent and
// remove notification
collapseOnMainThread();
@@ -350,6 +357,7 @@
final boolean canBubble = entry.canBubble();
if (canBubble) {
mLogger.logExpandingBubble(notificationKey);
+ removeHUN(row);
expandBubbleStackOnMainThread(entry);
} else {
startNotificationIntent(
@@ -422,14 +430,13 @@
boolean isActivityIntent) {
mLogger.logStartNotificationIntent(entry.getKey(), intent);
try {
- ActivityLaunchAnimator.Controller animationController = null;
- if (!wasOccluded && mStatusBar.areLaunchAnimationsEnabled()) {
- animationController = new StatusBarLaunchAnimatorController(
- mNotificationAnimationProvider.getAnimatorController(row), mStatusBar,
- isActivityIntent);
- }
+ ActivityLaunchAnimator.Controller animationController =
+ new StatusBarLaunchAnimatorController(
+ mNotificationAnimationProvider.getAnimatorController(row), mStatusBar,
+ isActivityIntent);
mActivityLaunchAnimator.startPendingIntentWithAnimation(animationController,
+ !wasOccluded && mStatusBar.areLaunchAnimationsEnabled(),
(adapter) -> {
long eventTime = row.getAndResetLastActionUpTime();
Bundle options = eventTime > 0
@@ -442,13 +449,6 @@
return intent.sendAndReturnResult(mContext, 0, fillInIntent, null,
null, null, options);
});
-
- // Note that other cases when we should still collapse (like activity already on top) is
- // handled by the StatusBarLaunchAnimatorController.
- boolean shouldCollapse = animationController == null;
- if (shouldCollapse) {
- collapseOnMainThread();
- }
} catch (PendingIntent.CanceledException e) {
// the stack trace isn't very helpful here.
// Just log the exception message.
@@ -462,34 +462,19 @@
ExpandableNotificationRow row) {
mActivityStarter.dismissKeyguardThenExecute(() -> {
AsyncTask.execute(() -> {
- ActivityLaunchAnimator.Controller animationController = null;
- if (mStatusBar.areLaunchAnimationsEnabled()) {
- animationController = new StatusBarLaunchAnimatorController(
- mNotificationAnimationProvider.getAnimatorController(row), mStatusBar,
- true /* isActivityIntent */);
- }
+ ActivityLaunchAnimator.Controller animationController =
+ new StatusBarLaunchAnimatorController(
+ mNotificationAnimationProvider.getAnimatorController(row),
+ mStatusBar, true /* isActivityIntent */);
mActivityLaunchAnimator.startIntentWithAnimation(
- animationController,
+ animationController, mStatusBar.areLaunchAnimationsEnabled(),
(adapter) -> TaskStackBuilder.create(mContext)
.addNextIntentWithParentStack(intent)
.startActivities(getActivityOptions(
mStatusBar.getDisplayId(),
adapter),
new UserHandle(UserHandle.getUserId(appUid))));
-
- // Note that other cases when we should still collapse (like activity already on
- // top) is handled by the StatusBarLaunchAnimatorController.
- boolean shouldCollapse = animationController == null;
-
- // Putting it back on the main thread, since we're touching views
- mMainThreadHandler.post(() -> {
- removeHUN(row);
- if (shouldCollapse) {
- mCommandQueue.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL,
- true /* force */);
- }
- });
});
return true;
}, null, false /* afterKeyguardGone */);
@@ -508,26 +493,16 @@
tsb.addNextIntent(intent);
}
- ActivityLaunchAnimator.Controller animationController = null;
- if (mStatusBar.areLaunchAnimationsEnabled()) {
- animationController = new StatusBarLaunchAnimatorController(
- ActivityLaunchAnimator.Controller.fromView(view), mStatusBar,
- true /* isActivityIntent */);
- }
+ ActivityLaunchAnimator.Controller animationController =
+ new StatusBarLaunchAnimatorController(
+ ActivityLaunchAnimator.Controller.fromView(view), mStatusBar,
+ true /* isActivityIntent */);
mActivityLaunchAnimator.startIntentWithAnimation(animationController,
+ mStatusBar.areLaunchAnimationsEnabled(),
(adapter) -> tsb.startActivities(
getActivityOptions(mStatusBar.getDisplayId(), adapter),
UserHandle.CURRENT));
-
- // Note that other cases when we should still collapse (like activity already on
- // top) is handled by the StatusBarLaunchAnimatorController.
- boolean shouldCollapse = animationController == null;
- if (shouldCollapse) {
- // Putting it back on the main thread, since we're touching views
- mMainThreadHandler.post(() -> mCommandQueue.animateCollapsePanels(
- CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */));
- }
});
return true;
}, null, false /* afterKeyguardGone */);
@@ -536,11 +511,6 @@
private void removeHUN(ExpandableNotificationRow row) {
String key = row.getEntry().getSbn().getKey();
if (mHeadsUpManager != null && mHeadsUpManager.isAlerting(key)) {
- // Release the HUN notification to the shade.
- if (mPresenter.isPresenterFullyCollapsed()) {
- HeadsUpUtil.setIsClickedHeadsUpNotification(row, true);
- }
-
// In most cases, when FLAG_AUTO_CANCEL is set, the notification will
// become canceled shortly by NoMan, but we can't assume that.
mHeadsUpManager.removeNotification(key, true /* releaseImmediately */);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
index 4795e8a..66e1c2e 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
@@ -103,7 +103,6 @@
import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
import com.android.systemui.statusbar.policy.UserSwitcherController;
-import com.android.systemui.tuner.TunerService;
import com.android.systemui.volume.VolumeComponent;
import com.android.systemui.wmshell.BubblesManager;
import com.android.wm.shell.bubbles.Bubbles;
@@ -214,7 +213,6 @@
OngoingCallController ongoingCallController,
SystemStatusAnimationScheduler animationScheduler,
PrivacyDotViewController dotViewController,
- TunerService tunerService,
FeatureFlags featureFlags,
KeyguardUnlockAnimationController keyguardUnlockAnimationController) {
return new StatusBar(
@@ -301,7 +299,6 @@
ongoingCallController,
animationScheduler,
dotViewController,
- tunerService,
featureFlags,
keyguardUnlockAnimationController);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyStateInflater.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyStateInflater.kt
index 0bf2d50..e3e2572 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyStateInflater.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyStateInflater.kt
@@ -341,7 +341,6 @@
activityStarter.startPendingIntentDismissingKeyguard(action.actionIntent, entry.row) {
smartReplyController
.smartActionClicked(entry, actionIndex, action, smartActions.fromAssistant)
- headsUpManager.removeNotification(entry.key, true /* releaseImmediately */)
}
}
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
index 5aacac2c..d07a8da 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
@@ -19,14 +19,21 @@
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
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;
+import android.app.smartspace.SmartspaceTarget;
import android.content.Context;
+import android.content.pm.UserInfo;
import android.content.res.Resources;
+import android.os.Handler;
+import android.os.UserHandle;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.util.AttributeSet;
@@ -47,6 +54,7 @@
import com.android.systemui.plugins.ClockPlugin;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
@@ -54,6 +62,7 @@
import com.android.systemui.statusbar.phone.NotificationIconContainer;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.util.settings.SecureSettings;
import org.junit.Before;
import org.junit.Test;
@@ -63,6 +72,8 @@
import org.mockito.MockitoAnnotations;
import org.mockito.verification.VerificationMode;
+import java.util.Collections;
+import java.util.List;
import java.util.concurrent.Executor;
@SmallTest
@@ -119,10 +130,19 @@
KeyguardUpdateMonitor mKeyguardUpdateMonitor;
@Mock
KeyguardBypassController mBypassController;
+ @Mock
+ Handler mHandler;
+ @Mock
+ UserTracker mUserTracker;
+ @Mock
+ SecureSettings mSecureSettings;
private KeyguardClockSwitchController mController;
private View mStatusArea;
+ private static final int USER_ID = 5;
+ private static final int MANAGED_USER_ID = 15;
+
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
@@ -159,7 +179,10 @@
mActivityStarter,
mFalsingManager,
mKeyguardUpdateMonitor,
- mBypassController
+ mBypassController,
+ mHandler,
+ mUserTracker,
+ mSecureSettings
);
when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE);
@@ -260,6 +283,89 @@
verify(mSmartspaceView, times(2)).setPrimaryTextColor(anyInt());
}
+ @Test
+ public void doNotFilterRegularTarget() {
+ setupPrimaryAndManagedUser();
+ mController.init();
+
+ when(mSecureSettings.getIntForUser(anyString(), anyInt(), eq(USER_ID))).thenReturn(0);
+ when(mSecureSettings.getIntForUser(anyString(), anyInt(), eq(MANAGED_USER_ID)))
+ .thenReturn(0);
+
+ mController.getSettingsObserver().onChange(true, null);
+
+ SmartspaceTarget t = mock(SmartspaceTarget.class);
+ when(t.isSensitive()).thenReturn(false);
+ when(t.getUserHandle()).thenReturn(new UserHandle(USER_ID));
+ assertEquals(false, mController.filterSmartspaceTarget(t));
+
+ reset(t);
+ when(t.isSensitive()).thenReturn(false);
+ when(t.getUserHandle()).thenReturn(new UserHandle(MANAGED_USER_ID));
+ assertEquals(false, mController.filterSmartspaceTarget(t));
+ }
+
+ @Test
+ public void filterAllSensitiveTargetsAllUsers() {
+ setupPrimaryAndManagedUser();
+ mController.init();
+
+ when(mSecureSettings.getIntForUser(anyString(), anyInt(), eq(USER_ID))).thenReturn(0);
+ when(mSecureSettings.getIntForUser(anyString(), anyInt(), eq(MANAGED_USER_ID)))
+ .thenReturn(0);
+
+ mController.getSettingsObserver().onChange(true, null);
+
+ SmartspaceTarget t = mock(SmartspaceTarget.class);
+ when(t.isSensitive()).thenReturn(true);
+ when(t.getUserHandle()).thenReturn(new UserHandle(USER_ID));
+ assertEquals(true, mController.filterSmartspaceTarget(t));
+
+ reset(t);
+ when(t.isSensitive()).thenReturn(true);
+ when(t.getUserHandle()).thenReturn(new UserHandle(MANAGED_USER_ID));
+ assertEquals(true, mController.filterSmartspaceTarget(t));
+ }
+
+ @Test
+ public void filterSensitiveManagedUserTargets() {
+ setupPrimaryAndManagedUser();
+ mController.init();
+
+ when(mSecureSettings.getIntForUser(anyString(), anyInt(), eq(USER_ID))).thenReturn(1);
+ when(mSecureSettings.getIntForUser(anyString(), anyInt(), eq(MANAGED_USER_ID)))
+ .thenReturn(0);
+
+ mController.getSettingsObserver().onChange(true, null);
+
+ SmartspaceTarget t = mock(SmartspaceTarget.class);
+ when(t.isSensitive()).thenReturn(true);
+ when(t.getUserHandle()).thenReturn(new UserHandle(USER_ID));
+ assertEquals(false, mController.filterSmartspaceTarget(t));
+
+ reset(t);
+ when(t.isSensitive()).thenReturn(true);
+ when(t.getUserHandle()).thenReturn(new UserHandle(MANAGED_USER_ID));
+ assertEquals(true, mController.filterSmartspaceTarget(t));
+ }
+
+ private void setupPrimaryAndManagedUser() {
+ UserInfo userInfo = mock(UserInfo.class);
+ when(userInfo.isManagedProfile()).thenReturn(true);
+ when(userInfo.getUserHandle()).thenReturn(new UserHandle(MANAGED_USER_ID));
+ when(mUserTracker.getUserProfiles()).thenReturn(List.of(userInfo));
+
+ when(mUserTracker.getUserId()).thenReturn(USER_ID);
+ when(mUserTracker.getUserHandle()).thenReturn(new UserHandle(USER_ID));
+ }
+
+ private void setupPrimaryAndNoManagedUser() {
+ when(mUserTracker.getUserProfiles()).thenReturn(Collections.emptyList());
+
+ when(mUserTracker.getUserId()).thenReturn(USER_ID);
+ when(mUserTracker.getUserHandle()).thenReturn(new UserHandle(USER_ID));
+ }
+
private void verifyAttachment(VerificationMode times) {
verify(mClockManager, times).addOnClockChangedListener(
any(ClockManager.ClockChangedListener.class));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityTargetAdapterTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityTargetAdapterTest.java
index 899625e..afd5f77 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityTargetAdapterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityTargetAdapterTest.java
@@ -65,9 +65,9 @@
mTargets.add(mAccessibilityTarget);
mAdapter = new AccessibilityTargetAdapter(mTargets);
- final View root = LayoutInflater.from(mContext).inflate(
+ final View rootView = LayoutInflater.from(mContext).inflate(
R.layout.accessibility_floating_menu_item, null);
- mViewHolder = new ViewHolder(root);
+ mViewHolder = new ViewHolder(rootView);
when(mAccessibilityTarget.getIcon()).thenReturn(mIcon);
when(mIcon.getConstantState()).thenReturn(mConstantState);
}
@@ -82,4 +82,27 @@
assertThat(actualIconWith).isEqualTo(iconWidthHeight);
}
+
+ @Test
+ public void getContentDescription_invisibleToggleTarget_descriptionWithoutState() {
+ when(mAccessibilityTarget.getFragmentType()).thenReturn(/* InvisibleToggle */ 1);
+ when(mAccessibilityTarget.getLabel()).thenReturn("testLabel");
+ when(mAccessibilityTarget.getStateDescription()).thenReturn("testState");
+
+ mAdapter.onBindViewHolder(mViewHolder, 0);
+
+ assertThat(mViewHolder.itemView.getContentDescription().toString().contentEquals(
+ "testLabel")).isTrue();
+ }
+
+ @Test
+ public void getStateDescription_toggleTarget_switchOff_stateOffText() {
+ when(mAccessibilityTarget.getFragmentType()).thenReturn(/* Toggle */ 2);
+ when(mAccessibilityTarget.getStateDescription()).thenReturn("testState");
+
+ mAdapter.onBindViewHolder(mViewHolder, 0);
+
+ assertThat(mViewHolder.itemView.getStateDescription().toString().contentEquals(
+ "testState")).isTrue();
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt
index c023610..fbba09a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt
@@ -44,12 +44,13 @@
private fun startIntentWithAnimation(
controller: ActivityLaunchAnimator.Controller? = this.controller,
+ animate: Boolean = true,
intentStarter: (RemoteAnimationAdapter?) -> Int
) {
// We start in a new thread so that we can ensure that the callbacks are called in the main
// thread.
thread {
- activityLaunchAnimator.startIntentWithAnimation(controller, intentStarter)
+ activityLaunchAnimator.startIntentWithAnimation(controller, animate, intentStarter)
}.join()
}
@@ -95,6 +96,16 @@
}
@Test
+ fun doesNotAnimateIfAnimateIsFalse() {
+ val willAnimateCaptor = ArgumentCaptor.forClass(Boolean::class.java)
+ startIntentWithAnimation(animate = false) { ActivityManager.START_SUCCESS }
+
+ waitForIdleSync()
+ verify(controller).onIntentStarted(willAnimateCaptor.capture())
+ assertFalse(willAnimateCaptor.value)
+ }
+
+ @Test
fun doesNotStartIfAnimationIsCancelled() {
val runner = activityLaunchAnimator.createRunner(controller)
runner.onAnimationCancelled()
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 ac24cde..bfd60b96 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataFilterTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataFilterTest.kt
@@ -25,6 +25,7 @@
import com.android.systemui.SysuiTestCase
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.statusbar.NotificationLockscreenUserManager
+import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Test
@@ -80,12 +81,13 @@
private lateinit var dataMain: MediaData
private lateinit var dataGuest: MediaData
private val device = MediaDeviceData(true, null, DEVICE_NAME)
+ private val clock = FakeSystemClock()
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
mediaDataFilter = MediaDataFilter(broadcastDispatcher, mediaResumeListener,
- lockscreenUserManager, executor)
+ lockscreenUserManager, executor, clock)
mediaDataFilter.mediaDataManager = mediaDataManager
mediaDataFilter.addListener(listener)
@@ -246,8 +248,9 @@
@Test
fun testOnSmartspaceMediaDataLoaded_noRecentMedia_nonEmptyRecommendation_usesSmartspace() {
- val dataOld = dataMain.copy(active = false, lastActive = 0L)
+ 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))
@@ -258,8 +261,9 @@
fun testOnSmartspaceMediaDataLoaded_noRecentMedia_emptyRecommendation_showsNothing() {
`when`(smartspaceData.iconGrid).thenReturn(listOf())
- val dataOld = dataMain.copy(active = false, lastActive = 0L)
+ 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, never())
@@ -270,7 +274,7 @@
@Test
fun testOnSmartspaceMediaDataLoaded_hasRecentMedia_usesMedia() {
// WHEN we have media that was recently played, but not currently active
- val dataCurrent = dataMain.copy(active = false, lastActive = System.currentTimeMillis())
+ val dataCurrent = dataMain.copy(active = false, lastActive = clock.elapsedRealtime())
mediaDataFilter.onMediaDataLoaded(KEY, null, dataCurrent)
verify(listener).onMediaDataLoaded(eq(KEY), eq(null), eq(dataCurrent))
@@ -294,7 +298,7 @@
@Test
fun testOnSmartspaceMediaDataRemoved_usedMedia_clearsMedia() {
- val dataCurrent = dataMain.copy(active = false, lastActive = System.currentTimeMillis())
+ val dataCurrent = dataMain.copy(active = false, lastActive = clock.elapsedRealtime())
mediaDataFilter.onMediaDataLoaded(KEY, null, dataCurrent)
mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
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 daa8b4b..acfc513 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt
@@ -81,11 +81,12 @@
lateinit var mediaDataManager: MediaDataManager
lateinit var mediaNotification: StatusBarNotification
@Captor lateinit var mediaDataCaptor: ArgumentCaptor<MediaData>
+ private val clock = FakeSystemClock()
@Before
fun setup() {
- foregroundExecutor = FakeExecutor(FakeSystemClock())
- backgroundExecutor = FakeExecutor(FakeSystemClock())
+ foregroundExecutor = FakeExecutor(clock)
+ backgroundExecutor = FakeExecutor(clock)
smartspaceMediaDataProvider = SmartspaceMediaDataProvider()
mediaDataManager = MediaDataManager(
context = context,
@@ -103,7 +104,8 @@
activityStarter = activityStarter,
smartspaceMediaDataProvider = smartspaceMediaDataProvider,
useMediaResumption = true,
- useQsMediaPlayer = true
+ useQsMediaPlayer = true,
+ systemClock = clock
)
session = MediaSession(context, "MediaDataManagerTestSession")
mediaNotification = SbnBuilder().run {
@@ -310,7 +312,7 @@
setTitle(SESSION_TITLE)
build()
}
- val currentTimeMillis = System.currentTimeMillis()
+ val currentTime = clock.elapsedRealtime()
mediaDataManager.addResumptionControls(USER_ID, desc, Runnable {}, session.sessionToken,
APP_NAME, pendingIntent, PACKAGE_NAME)
assertThat(backgroundExecutor.runAllReady()).isEqualTo(1)
@@ -322,7 +324,7 @@
assertThat(data.song).isEqualTo(SESSION_TITLE)
assertThat(data.app).isEqualTo(APP_NAME)
assertThat(data.actions).hasSize(1)
- assertThat(data.lastActive).isAtLeast(currentTimeMillis)
+ assertThat(data.lastActive).isAtLeast(currentTime)
}
@Test
@@ -380,12 +382,12 @@
@Test
fun testOnMediaDataChanged_updatesLastActiveTime() {
- val currentTimeMillis = System.currentTimeMillis()
+ val currentTime = clock.elapsedRealtime()
mediaDataManager.onNotificationAdded(KEY, mediaNotification)
assertThat(backgroundExecutor.runAllReady()).isEqualTo(1)
assertThat(foregroundExecutor.runAllReady()).isEqualTo(1)
verify(listener).onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor))
- assertThat(mediaDataCaptor.value!!.lastActive).isAtLeast(currentTimeMillis)
+ assertThat(mediaDataCaptor.value!!.lastActive).isAtLeast(currentTime)
}
@Test
@@ -396,12 +398,13 @@
assertThat(foregroundExecutor.runAllReady()).isEqualTo(1)
// WHEN the notification times out
- val currentTimeMillis = System.currentTimeMillis()
+ clock.advanceTime(100)
+ val currentTime = clock.elapsedRealtime()
mediaDataManager.setTimedOut(KEY, true, true)
// THEN the last active time is not changed
verify(listener).onMediaDataLoaded(eq(KEY), eq(KEY), capture(mediaDataCaptor))
- assertThat(mediaDataCaptor.value.lastActive).isLessThan(currentTimeMillis)
+ assertThat(mediaDataCaptor.value.lastActive).isLessThan(currentTime)
}
@Test
@@ -417,13 +420,14 @@
mediaDataManager.onMediaDataLoaded(KEY, null, data.copy(resumeAction = Runnable {}))
// WHEN the notification is removed
- val currentTimeMillis = System.currentTimeMillis()
+ clock.advanceTime(100)
+ val currentTime = clock.elapsedRealtime()
mediaDataManager.onNotificationRemoved(KEY)
// THEN the last active time is not changed
verify(listener).onMediaDataLoaded(eq(PACKAGE_NAME), eq(KEY), capture(mediaDataCaptor))
assertThat(mediaDataCaptor.value.resumption).isTrue()
- assertThat(mediaDataCaptor.value.lastActive).isLessThan(currentTimeMillis)
+ assertThat(mediaDataCaptor.value.lastActive).isLessThan(currentTime)
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarRotationContextTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarRotationContextTest.java
index 47f4183..b85af48 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarRotationContextTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarRotationContextTest.java
@@ -62,8 +62,8 @@
final View view = new View(mContext);
mRotationButton = mock(RotationButton.class);
- mRotationButtonController = spy(new RotationButtonController(mContext, 0, 0,
- mRotationButton, (visibility) -> {}));
+ mRotationButtonController = spy(new RotationButtonController(mContext, 0, 0));
+ mRotationButtonController.setRotationButton(mRotationButton, (visibility) -> {});
final KeyButtonDrawable kbd = mock(KeyButtonDrawable.class);
doReturn(view).when(mRotationButton).getCurrentView();
doReturn(true).when(mRotationButton).acceptRotationProposal();
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 2f28b13..5cdad05 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
@@ -207,7 +207,25 @@
}
@Test
- public void testHandleClick_hasCards_startWalletActivity() {
+ public void testHandleClick_hasCards_deviceLocked_startWalletActivity() {
+ when(mKeyguardStateController.isUnlocked()).thenReturn(false);
+ setUpWalletCard(/* hasCard= */ true);
+
+ mTile.handleClick(null /* view */);
+ mTestableLooper.processAllMessages();
+
+ verify(mSpiedContext).startActivity(mIntentCaptor.capture());
+
+ Intent nextStartedIntent = mIntentCaptor.getValue();
+ String walletClassName = "com.android.systemui.wallet.ui.WalletActivity";
+
+ assertNotNull(nextStartedIntent);
+ assertThat(nextStartedIntent.getComponent().getClassName()).isEqualTo(walletClassName);
+ }
+
+ @Test
+ public void testHandleClick_hasCards_deviceUnlocked_startWalletActivity() {
+ when(mKeyguardStateController.isUnlocked()).thenReturn(true);
setUpWalletCard(/* hasCard= */ true);
mTile.handleClick(null /* view */);
@@ -226,7 +244,7 @@
@Test
public void testHandleUpdateState_updateLabelAndIcon() {
QSTile.State state = new QSTile.State();
- QSTile.Icon icon = QSTileImpl.ResourceIcon.get(R.drawable.ic_qs_wallet);
+ QSTile.Icon icon = QSTileImpl.ResourceIcon.get(R.drawable.ic_wallet_lockscreen);
mTile.handleUpdateState(state, null);
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 7dcfc6b..b6eb492 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
@@ -50,7 +50,6 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.dock.DockManager;
import com.android.systemui.scrim.ScrimView;
-import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.concurrency.FakeExecutor;
@@ -107,8 +106,6 @@
private DockManager mDockManager;
@Mock
private ConfigurationController mConfigurationController;
- @Mock
- private FeatureFlags mFeatureFlags;
private static class AnimatorListener implements Animator.AnimatorListener {
@@ -217,14 +214,12 @@
when(mDelayedWakeLockBuilder.setTag(any(String.class)))
.thenReturn(mDelayedWakeLockBuilder);
when(mDelayedWakeLockBuilder.build()).thenReturn(mWakeLock);
- when(mFeatureFlags.isShadeOpaque()).thenReturn(true);
when(mDockManager.isDocked()).thenReturn(false);
mScrimController = new ScrimController(mLightBarController,
mDozeParameters, mAlarmManager, mKeyguardStateController, mDelayedWakeLockBuilder,
new FakeHandler(mLooper.getLooper()), mKeyguardUpdateMonitor,
- mDockManager, mConfigurationController, mFeatureFlags,
- new FakeExecutor(new FakeSystemClock()));
+ mDockManager, mConfigurationController, new FakeExecutor(new FakeSystemClock()));
mScrimController.setScrimVisibleListener(visible -> mScrimVisibility = visible);
mScrimController.attachViews(mScrimBehind, mNotificationsScrim, mScrimInFront,
mScrimForBubble);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
index 5170168..be86af5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
@@ -61,6 +61,7 @@
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.NotificationShadeDepthController;
import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.notification.NotificationActivityStarter;
@@ -73,6 +74,7 @@
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
import com.android.systemui.statusbar.notification.row.OnUserInteractionCallback;
+import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.time.FakeSystemClock;
@@ -184,6 +186,14 @@
when(mOnUserInteractionCallback.getGroupSummaryToDismiss(mNotificationRow.getEntry()))
.thenReturn(null);
+ HeadsUpManagerPhone headsUpManager = mock(HeadsUpManagerPhone.class);
+ NotificationLaunchAnimatorControllerProvider notificationAnimationProvider =
+ new NotificationLaunchAnimatorControllerProvider(
+ mock(NotificationShadeWindowViewController.class), mock(
+ NotificationListContainer.class),
+ mock(NotificationShadeDepthController.class),
+ headsUpManager);
+
mNotificationActivityStarter =
new StatusBarNotificationActivityStarter.Builder(
getContext(),
@@ -192,7 +202,7 @@
mUiBgExecutor,
mEntryManager,
mNotifPipeline,
- mock(HeadsUpManagerPhone.class),
+ headsUpManager,
mActivityStarter,
mClickNotifier,
mock(StatusBarStateController.class),
@@ -220,8 +230,7 @@
.setNotificationPanelViewController(
mock(NotificationPanelViewController.class))
.setActivityLaunchAnimator(mActivityLaunchAnimator)
- .setNotificationAnimatorControllerProvider(
- mock(NotificationLaunchAnimatorControllerProvider.class))
+ .setNotificationAnimatorControllerProvider(notificationAnimationProvider)
.build();
// set up dismissKeyguardThenExecute to synchronously invoke the OnDismissAction arg
@@ -259,7 +268,8 @@
// Then
verify(mShadeController, atLeastOnce()).collapsePanel();
- verify(mActivityLaunchAnimator).startPendingIntentWithAnimation(eq(null), any());
+ verify(mActivityLaunchAnimator).startPendingIntentWithAnimation(any(),
+ eq(false) /* animate */, any());
verify(mAssistManager).hideAssist();
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 8c8212cd..545e2e0 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
@@ -146,7 +146,6 @@
import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
import com.android.systemui.statusbar.policy.UserSwitcherController;
-import com.android.systemui.tuner.TunerService;
import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.time.FakeSystemClock;
import com.android.systemui.volume.VolumeComponent;
@@ -269,7 +268,6 @@
@Mock private OngoingCallController mOngoingCallController;
@Mock private SystemStatusAnimationScheduler mAnimationScheduler;
@Mock private PrivacyDotViewController mDotViewController;
- @Mock private TunerService mTunerService;
@Mock private FeatureFlags mFeatureFlags;
@Mock private IWallpaperManager mWallpaperManager;
@Mock private KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
@@ -440,7 +438,6 @@
mOngoingCallController,
mAnimationScheduler,
mDotViewController,
- mTunerService,
mFeatureFlags,
mKeyguardUnlockAnimationController);
when(mKeyguardViewMediator.registerStatusBar(any(StatusBar.class), any(ViewGroup.class),
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 ab7cbf7..bfb98de 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
@@ -4,6 +4,7 @@
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.Matchers.anyLong;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -309,6 +310,7 @@
// Put RSSI in the middle of the range.
rssi += amountPerLevel / 2;
when(mVcnTransportInfo.getWifiInfo()).thenReturn(mWifiInfo);
+ when(mVcnTransportInfo.makeCopy(anyLong())).thenReturn(mVcnTransportInfo);
when(mWifiInfo.getRssi()).thenReturn(rssi);
when(mWifiInfo.isCarrierMerged()).thenReturn(true);
when(mWifiInfo.getSubscriptionId()).thenReturn(1);
@@ -318,6 +320,7 @@
protected void setWifiStateForVcn(boolean connected, String ssid) {
when(mVcnTransportInfo.getWifiInfo()).thenReturn(mWifiInfo);
+ when(mVcnTransportInfo.makeCopy(anyLong())).thenReturn(mVcnTransportInfo);
when(mWifiInfo.getSSID()).thenReturn(ssid);
when(mWifiInfo.isCarrierMerged()).thenReturn(true);
when(mWifiInfo.getSubscriptionId()).thenReturn(1);
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index c5246c7..85ff2be 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -312,19 +312,6 @@
mContext.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED,
"Need BLUETOOTH_PRIVILEGED permission");
- final long token = Binder.clearCallingIdentity();
- try {
- return onFactoryResetInternal(attributionSource);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- private boolean onFactoryResetInternal(AttributionSource attributionSource) {
// Wait for stable state if bluetooth is temporary state.
int state = getState();
if (state == BluetoothAdapter.STATE_BLE_TURNING_ON
@@ -347,7 +334,7 @@
addActiveLog(
BluetoothProtoEnums.ENABLE_DISABLE_REASON_FACTORY_RESET,
mContext.getPackageName(), false);
- mBluetooth.onBrEdrDown();
+ mBluetooth.onBrEdrDown(attributionSource);
return true;
} else if (state == BluetoothAdapter.STATE_ON) {
addActiveLog(
@@ -404,7 +391,7 @@
addActiveLog(
BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE,
mContext.getPackageName(), false);
- mBluetooth.onBrEdrDown();
+ mBluetooth.onBrEdrDown(mContext.getAttributionSource());
mEnable = false;
mEnableExternal = false;
}
@@ -888,7 +875,7 @@
if (mBluetooth != null) {
addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST,
mContext.getPackageName(), false);
- mBluetooth.onBrEdrDown();
+ mBluetooth.onBrEdrDown(mContext.getAttributionSource());
}
} catch (RemoteException e) {
Slog.e(TAG, "error when disabling bluetooth", e);
@@ -1037,7 +1024,7 @@
if (!mEnableExternal) {
addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST,
packageName, false);
- sendBrEdrDownCallback();
+ sendBrEdrDownCallback(attributionSource);
}
}
return true;
@@ -1074,12 +1061,12 @@
if (!mEnableExternal && !isBleAppPresent()) {
Slog.i(TAG, "Bluetooth was disabled while enabling BLE, disable BLE now");
mEnable = false;
- mBluetooth.onBrEdrDown();
+ mBluetooth.onBrEdrDown(mContext.getAttributionSource());
return;
}
if (isBluetoothPersistedStateOnBluetooth() || !isBleAppPresent()) {
// This triggers transition to STATE_ON
- mBluetooth.onLeServiceUp();
+ mBluetooth.onLeServiceUp(mContext.getAttributionSource());
persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH);
}
} catch (RemoteException e) {
@@ -1097,7 +1084,7 @@
android.Manifest.permission.BLUETOOTH_CONNECT,
android.Manifest.permission.BLUETOOTH_PRIVILEGED,
})
- private void sendBrEdrDownCallback() {
+ private void sendBrEdrDownCallback(AttributionSource attributionSource) {
if (DBG) {
Slog.d(TAG, "Calling sendBrEdrDownCallback callbacks");
}
@@ -1110,7 +1097,7 @@
if (isBleAppPresent()) {
// Need to stay at BLE ON. Disconnect all Gatt connections
try {
- mBluetoothGatt.unregAll(mContext.getAttributionSource());
+ mBluetoothGatt.unregAll(attributionSource);
} catch (RemoteException e) {
Slog.e(TAG, "Unable to disconnect all apps.", e);
}
@@ -1118,7 +1105,7 @@
try {
mBluetoothLock.readLock().lock();
if (mBluetooth != null) {
- mBluetooth.onBrEdrDown();
+ mBluetooth.onBrEdrDown(attributionSource);
}
} catch (RemoteException e) {
Slog.e(TAG, "Call to onBrEdrDown() failed.", e);
@@ -1319,7 +1306,8 @@
if (mBluetooth != null) {
//Unregister callback object
try {
- mBluetooth.unregisterCallback(mBluetoothCallback);
+ mBluetooth.unregisterCallback(mBluetoothCallback,
+ mContext.getAttributionSource());
} catch (RemoteException re) {
Slog.e(TAG, "Unable to unregister BluetoothCallback", re);
}
@@ -1729,7 +1717,7 @@
try {
mBluetoothLock.readLock().lock();
if (mBluetooth != null) {
- return mBluetooth.getAddressWithAttribution(mContext.getAttributionSource());
+ return mBluetooth.getAddressWithAttribution(attributionSource);
}
} catch (RemoteException e) {
Slog.e(TAG,
@@ -1758,7 +1746,7 @@
try {
mBluetoothLock.readLock().lock();
if (mBluetooth != null) {
- return mBluetooth.getName(mContext.getAttributionSource());
+ return mBluetooth.getName(attributionSource);
}
} catch (RemoteException e) {
Slog.e(TAG, "getName(): Unable to retrieve name remotely. Returning cached name", e);
@@ -1886,7 +1874,7 @@
int state = mBluetooth.getState();
if (state == BluetoothAdapter.STATE_BLE_ON) {
Slog.w(TAG, "BT Enable in BLE_ON State, going to ON");
- mBluetooth.onLeServiceUp();
+ mBluetooth.onLeServiceUp(mContext.getAttributionSource());
persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH);
break;
}
@@ -2105,7 +2093,8 @@
//Register callback object
try {
- mBluetooth.registerCallback(mBluetoothCallback);
+ mBluetooth.registerCallback(mBluetoothCallback,
+ mContext.getAttributionSource());
} catch (RemoteException re) {
Slog.e(TAG, "Unable to register BluetoothCallback", re);
}
@@ -2342,7 +2331,8 @@
try {
mBluetoothLock.readLock().lock();
if (mBluetooth != null) {
- mBluetooth.unregisterCallback(mBluetoothCallback);
+ mBluetooth.unregisterCallback(mBluetoothCallback,
+ mContext.getAttributionSource());
}
} catch (RemoteException re) {
Slog.e(TAG, "Unable to unregister", re);
@@ -2569,7 +2559,7 @@
sendBluetoothStateCallback(false); // BT is OFF for general users
// Broadcast as STATE_OFF
newState = BluetoothAdapter.STATE_OFF;
- sendBrEdrDownCallback();
+ sendBrEdrDownCallback(mContext.getAttributionSource());
}
} else if (newState == BluetoothAdapter.STATE_ON) {
boolean isUp = (newState == BluetoothAdapter.STATE_ON);
@@ -2670,7 +2660,7 @@
mBluetoothLock.readLock().lock();
if (mBluetooth != null) {
//Unregister callback object
- mBluetooth.unregisterCallback(mBluetoothCallback);
+ mBluetooth.unregisterCallback(mBluetoothCallback, mContext.getAttributionSource());
}
} catch (RemoteException re) {
Slog.e(TAG, "Unable to unregister", re);
@@ -2890,6 +2880,7 @@
}
}
+ @SuppressLint("AndroidFrameworkRequiresPermission")
private static boolean checkPermissionForDataDelivery(Context context, String permission,
AttributionSource attributionSource, String message) {
final int result = PermissionChecker.checkPermissionForDataDeliveryFromDataSource(
@@ -2916,6 +2907,7 @@
*
* <p>Should be used in situations where the app op should not be noted.
*/
+ @SuppressLint("AndroidFrameworkRequiresPermission")
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public static boolean checkConnectPermissionForDataDelivery(
Context context, AttributionSource attributionSource, String message) {
diff --git a/services/core/java/com/android/server/SensorPrivacyService.java b/services/core/java/com/android/server/SensorPrivacyService.java
index cd3dca9..0f73897 100644
--- a/services/core/java/com/android/server/SensorPrivacyService.java
+++ b/services/core/java/com/android/server/SensorPrivacyService.java
@@ -203,7 +203,7 @@
SparseBooleanArray userIndividualEnabled =
mIndividualEnabled.valueAt(i);
for (int j = 0; j < userIndividualEnabled.size(); j++) {
- int sensor = userIndividualEnabled.keyAt(i);
+ int sensor = userIndividualEnabled.keyAt(j);
boolean enabled = userIndividualEnabled.valueAt(j);
setUserRestriction(userId, sensor, enabled);
}
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 0c785da..a1a4418 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -1850,7 +1850,7 @@
public StorageManagerService(Context context) {
sSelf = this;
mVoldAppDataIsolationEnabled = SystemProperties.getBoolean(
- ANDROID_VOLD_APP_DATA_ISOLATION_ENABLED_PROPERTY, false);
+ ANDROID_VOLD_APP_DATA_ISOLATION_ENABLED_PROPERTY, true);
mContext = context;
mResolver = mContext.getContentResolver();
mCallbacks = new Callbacks(FgThread.get().getLooper());
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java
index bf57452..d8eccef 100644
--- a/services/core/java/com/android/server/am/ActivityManagerConstants.java
+++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java
@@ -16,6 +16,9 @@
package com.android.server.am;
+import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED;
+import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_NONE;
+
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_POWER_QUICK;
import android.app.ActivityThread;
@@ -27,6 +30,7 @@
import android.os.Build;
import android.os.Handler;
import android.os.Message;
+import android.os.PowerExemptionManager;
import android.provider.DeviceConfig;
import android.provider.DeviceConfig.OnPropertiesChangedListener;
import android.provider.DeviceConfig.Properties;
@@ -139,6 +143,11 @@
private static final long DEFAULT_FG_TO_BG_FGS_GRACE_DURATION = 5 * 1000;
private static final int DEFAULT_FGS_START_FOREGROUND_TIMEOUT_MS = 10 * 1000;
private static final float DEFAULT_FGS_ATOM_SAMPLE_RATE = 1; // 100 %
+ /**
+ * Same as {@link TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED}
+ */
+ private static final int
+ DEFAULT_PUSH_MESSAGING_OVER_QUOTA_BEHAVIOR = 1;
// Flag stored in the DeviceConfig API.
/**
@@ -210,6 +219,13 @@
private static final String KEY_DEFERRED_FGS_NOTIFICATION_EXCLUSION_TIME =
"deferred_fgs_notification_exclusion_time";
+ /**
+ * Default value for mPushMessagingOverQuotaBehavior if not explicitly set in
+ * Settings.Global.
+ */
+ private static final String KEY_PUSH_MESSAGING_OVER_QUOTA_BEHAVIOR =
+ "push_messaging_over_quota_behavior";
+
// Maximum number of cached processes we will allow.
public int MAX_CACHED_PROCESSES = DEFAULT_MAX_CACHED_PROCESSES;
@@ -413,6 +429,13 @@
// before another FGS notifiction from that app can be deferred.
volatile long mFgsNotificationDeferralExclusionTime = 2 * 60 * 1000L;
+ /**
+ * When server pushing message is over the quote, select one of the temp allow list type as
+ * defined in {@link PowerExemptionManager.TempAllowListType}
+ */
+ volatile @PowerExemptionManager.TempAllowListType int mPushMessagingOverQuotaBehavior =
+ DEFAULT_PUSH_MESSAGING_OVER_QUOTA_BEHAVIOR;
+
/*
* At boot time, broadcast receiver ACTION_BOOT_COMPLETED, ACTION_LOCKED_BOOT_COMPLETED and
* ACTION_PRE_BOOT_COMPLETED are temp allowlisted to start FGS for a duration of time in
@@ -605,6 +628,9 @@
case KEY_DEFERRED_FGS_NOTIFICATION_EXCLUSION_TIME:
updateFgsNotificationDeferralExclusionTime();
break;
+ case KEY_PUSH_MESSAGING_OVER_QUOTA_BEHAVIOR:
+ updatePushMessagingOverQuotaBehavior();
+ break;
case KEY_OOMADJ_UPDATE_POLICY:
updateOomAdjUpdatePolicy();
break;
@@ -909,6 +935,19 @@
/*default value*/ 2 * 60 * 1000L);
}
+ private void updatePushMessagingOverQuotaBehavior() {
+ mPushMessagingOverQuotaBehavior = DeviceConfig.getInt(
+ DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+ KEY_PUSH_MESSAGING_OVER_QUOTA_BEHAVIOR,
+ DEFAULT_PUSH_MESSAGING_OVER_QUOTA_BEHAVIOR);
+ if (mPushMessagingOverQuotaBehavior < TEMPORARY_ALLOW_LIST_TYPE_NONE
+ || mPushMessagingOverQuotaBehavior
+ > TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED) {
+ mPushMessagingOverQuotaBehavior =
+ DEFAULT_PUSH_MESSAGING_OVER_QUOTA_BEHAVIOR;
+ }
+ }
+
private void updateOomAdjUpdatePolicy() {
OOMADJ_UPDATE_QUICK = DeviceConfig.getInt(
DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
@@ -1166,6 +1205,8 @@
pw.print("="); pw.println(mFgsStartRestrictionCheckCallerTargetSdk);
pw.print(" "); pw.print(KEY_FGS_ATOM_SAMPLE_RATE);
pw.print("="); pw.println(mDefaultFgsAtomSampleRate);
+ pw.print(" "); pw.print(KEY_PUSH_MESSAGING_OVER_QUOTA_BEHAVIOR);
+ pw.print("="); pw.println(mPushMessagingOverQuotaBehavior);
pw.println();
if (mOverrideMaxCachedProcesses >= 0) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 00b13b1..9aedf15 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -51,7 +51,8 @@
import static android.os.IServiceManager.DUMP_FLAG_PROTO;
import static android.os.InputConstants.DEFAULT_DISPATCHING_TIMEOUT_MILLIS;
import static android.os.PowerExemptionManager.REASON_SYSTEM_ALLOW_LISTED;
-import static android.os.PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
+import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
+import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_NONE;
import static android.os.Process.BLUETOOTH_UID;
import static android.os.Process.FIRST_APPLICATION_UID;
import static android.os.Process.INVALID_UID;
@@ -14603,15 +14604,20 @@
*/
@GuardedBy("this")
void tempAllowlistUidLocked(int targetUid, long duration, @ReasonCode int reasonCode,
- String reason, int type, int callingUid) {
+ String reason, @TempAllowListType int type, int callingUid) {
synchronized (mProcLock) {
+ // The temp allowlist type could change according to the reasonCode.
+ type = mLocalDeviceIdleController.getTempAllowListType(reasonCode, type);
+ if (type == TEMPORARY_ALLOW_LIST_TYPE_NONE) {
+ return;
+ }
mPendingTempAllowlist.put(targetUid,
new PendingTempAllowlist(targetUid, duration, reasonCode, reason, type,
callingUid));
setUidTempAllowlistStateLSP(targetUid, true);
mUiHandler.obtainMessage(PUSH_TEMP_ALLOWLIST_UI_MSG).sendToTarget();
- if (type == TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED) {
+ if (type == TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED) {
mFgsStartTempAllowList.add(targetUid, duration,
new FgsTempAllowListItem(duration, reasonCode, reason, callingUid));
}
@@ -15285,7 +15291,7 @@
synchronized (mProcLock) {
mDeviceIdleTempAllowlist = appids;
if (adding) {
- if (type == TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED) {
+ if (type == TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED) {
mFgsStartTempAllowList.add(changingUid, durationMs,
new FgsTempAllowListItem(durationMs, reasonCode, reason,
callingUid));
@@ -16152,6 +16158,13 @@
return mServices.canAllowWhileInUsePermissionInFgsLocked(pid, uid, packageName);
}
}
+
+ @Override
+ public @TempAllowListType int getPushMessagingOverQuotaBehavior() {
+ synchronized (ActivityManagerService.this) {
+ return mConstants.mPushMessagingOverQuotaBehavior;
+ }
+ }
}
long inputDispatchingTimedOut(int pid, final boolean aboveSystem, String reason) {
diff --git a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
index 859cc44..406e866 100644
--- a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
+++ b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
@@ -663,7 +663,7 @@
final long gnssChargeUC = measuredEnergyDeltas.gnssChargeUC;
if (gnssChargeUC != MeasuredEnergySnapshot.UNAVAILABLE) {
- mStats.updateGnssMeasuredEnergyStatsLocked(displayChargeUC, elapsedRealtime);
+ mStats.updateGnssMeasuredEnergyStatsLocked(gnssChargeUC, elapsedRealtime);
}
}
// Inform mStats about each applicable custom energy bucket.
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 5a9c4de..2a39326 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -792,7 +792,7 @@
mAppDataIsolationEnabled =
SystemProperties.getBoolean(ANDROID_APP_DATA_ISOLATION_ENABLED_PROPERTY, true);
mVoldAppDataIsolationEnabled = SystemProperties.getBoolean(
- ANDROID_VOLD_APP_DATA_ISOLATION_ENABLED_PROPERTY, false);
+ ANDROID_VOLD_APP_DATA_ISOLATION_ENABLED_PROPERTY, true);
mAppDataIsolationAllowlistedApps = new ArrayList<>(
SystemConfig.getInstance().getAppDataIsolationWhitelistedApps());
diff --git a/services/core/java/com/android/server/apphibernation/AppHibernationService.java b/services/core/java/com/android/server/apphibernation/AppHibernationService.java
index 52388ff..9396241 100644
--- a/services/core/java/com/android/server/apphibernation/AppHibernationService.java
+++ b/services/core/java/com/android/server/apphibernation/AppHibernationService.java
@@ -393,6 +393,7 @@
Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "unhibernatePackage");
pkgState.hibernated = false;
pkgState.lastUnhibernatedMs = System.currentTimeMillis();
+ final long caller = Binder.clearCallingIdentity();
// Deliver LOCKED_BOOT_COMPLETE AND BOOT_COMPLETE broadcast so app can re-register
// their alarms/jobs/etc.
try {
@@ -435,8 +436,10 @@
userId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
+ } finally {
+ Binder.restoreCallingIdentity(caller);
+ Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
- Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
/**
diff --git a/services/core/java/com/android/server/biometrics/OWNERS b/services/core/java/com/android/server/biometrics/OWNERS
index 8765c9a..4eac972 100644
--- a/services/core/java/com/android/server/biometrics/OWNERS
+++ b/services/core/java/com/android/server/biometrics/OWNERS
@@ -5,3 +5,4 @@
curtislb@google.com
ilyamaty@google.com
joshmccloskey@google.com
+jbolinger@google.com
diff --git a/services/core/java/com/android/server/biometrics/sensors/RevokeChallengeClient.java b/services/core/java/com/android/server/biometrics/sensors/RevokeChallengeClient.java
index 90fa1b4..7f86c62 100644
--- a/services/core/java/com/android/server/biometrics/sensors/RevokeChallengeClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/RevokeChallengeClient.java
@@ -42,7 +42,6 @@
super.start(callback);
startHalOperation();
- mCallback.onClientFinished(this, true /* success */);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/AidlConversionUtils.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/AidlConversionUtils.java
index 5d713f3..043260c 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/AidlConversionUtils.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/AidlConversionUtils.java
@@ -24,11 +24,14 @@
import android.hardware.biometrics.face.BaseFrame;
import android.hardware.biometrics.face.Cell;
import android.hardware.biometrics.face.EnrollmentFrame;
+import android.hardware.biometrics.face.EnrollmentStage;
import android.hardware.biometrics.face.Error;
import android.hardware.face.FaceAuthenticationFrame;
import android.hardware.face.FaceDataFrame;
import android.hardware.face.FaceEnrollCell;
import android.hardware.face.FaceEnrollFrame;
+import android.hardware.face.FaceEnrollStages;
+import android.hardware.face.FaceEnrollStages.FaceEnrollStage;
/**
* Utilities for converting from hardware to framework-defined AIDL models.
@@ -38,92 +41,107 @@
private AidlConversionUtils() {
}
- public static @BiometricFaceConstants.FaceError int toFrameworkError(byte aidlError) {
- if (aidlError == Error.UNKNOWN) {
- // No framework constant available
- return BiometricFaceConstants.FACE_ERROR_UNKNOWN;
- } else if (aidlError == Error.HW_UNAVAILABLE) {
- return BiometricFaceConstants.FACE_ERROR_HW_UNAVAILABLE;
- } else if (aidlError == Error.UNABLE_TO_PROCESS) {
- return BiometricFaceConstants.FACE_ERROR_UNABLE_TO_PROCESS;
- } else if (aidlError == Error.TIMEOUT) {
- return BiometricFaceConstants.FACE_ERROR_TIMEOUT;
- } else if (aidlError == Error.NO_SPACE) {
- return BiometricFaceConstants.FACE_ERROR_NO_SPACE;
- } else if (aidlError == Error.CANCELED) {
- return BiometricFaceConstants.FACE_ERROR_CANCELED;
- } else if (aidlError == Error.UNABLE_TO_REMOVE) {
- return BiometricFaceConstants.FACE_ERROR_UNABLE_TO_REMOVE;
- } else if (aidlError == Error.VENDOR) {
- return BiometricFaceConstants.FACE_ERROR_VENDOR;
- } else if (aidlError == Error.REENROLL_REQUIRED) {
- return BiometricFaceConstants.BIOMETRIC_ERROR_RE_ENROLL;
- } else {
- return BiometricFaceConstants.FACE_ERROR_UNKNOWN;
+ @BiometricFaceConstants.FaceError
+ public static int toFrameworkError(byte aidlError) {
+ switch (aidlError) {
+ case Error.HW_UNAVAILABLE:
+ return BiometricFaceConstants.FACE_ERROR_HW_UNAVAILABLE;
+ case Error.UNABLE_TO_PROCESS:
+ return BiometricFaceConstants.FACE_ERROR_UNABLE_TO_PROCESS;
+ case Error.TIMEOUT:
+ return BiometricFaceConstants.FACE_ERROR_TIMEOUT;
+ case Error.NO_SPACE:
+ return BiometricFaceConstants.FACE_ERROR_NO_SPACE;
+ case Error.CANCELED:
+ return BiometricFaceConstants.FACE_ERROR_CANCELED;
+ case Error.UNABLE_TO_REMOVE:
+ return BiometricFaceConstants.FACE_ERROR_UNABLE_TO_REMOVE;
+ case Error.VENDOR:
+ return BiometricFaceConstants.FACE_ERROR_VENDOR;
+ case Error.REENROLL_REQUIRED:
+ return BiometricFaceConstants.BIOMETRIC_ERROR_RE_ENROLL;
+ case Error.UNKNOWN:
+ default:
+ return BiometricFaceConstants.FACE_ERROR_UNKNOWN;
}
}
- public static @BiometricFaceConstants.FaceAcquired int toFrameworkAcquiredInfo(
- byte aidlAcquired) {
- if (aidlAcquired == AcquiredInfo.UNKNOWN) {
- return BiometricFaceConstants.FACE_ACQUIRED_UNKNOWN;
- } else if (aidlAcquired == AcquiredInfo.GOOD) {
- return BiometricFaceConstants.FACE_ACQUIRED_GOOD;
- } else if (aidlAcquired == AcquiredInfo.INSUFFICIENT) {
- return BiometricFaceConstants.FACE_ACQUIRED_INSUFFICIENT;
- } else if (aidlAcquired == AcquiredInfo.TOO_BRIGHT) {
- return BiometricFaceConstants.FACE_ACQUIRED_TOO_BRIGHT;
- } else if (aidlAcquired == AcquiredInfo.TOO_DARK) {
- return BiometricFaceConstants.FACE_ACQUIRED_TOO_DARK;
- } else if (aidlAcquired == AcquiredInfo.TOO_CLOSE) {
- return BiometricFaceConstants.FACE_ACQUIRED_TOO_CLOSE;
- } else if (aidlAcquired == AcquiredInfo.TOO_FAR) {
- return BiometricFaceConstants.FACE_ACQUIRED_TOO_FAR;
- } else if (aidlAcquired == AcquiredInfo.FACE_TOO_HIGH) {
- return BiometricFaceConstants.FACE_ACQUIRED_TOO_HIGH;
- } else if (aidlAcquired == AcquiredInfo.FACE_TOO_LOW) {
- return BiometricFaceConstants.FACE_ACQUIRED_TOO_LOW;
- } else if (aidlAcquired == AcquiredInfo.FACE_TOO_RIGHT) {
- return BiometricFaceConstants.FACE_ACQUIRED_TOO_RIGHT;
- } else if (aidlAcquired == AcquiredInfo.FACE_TOO_LEFT) {
- return BiometricFaceConstants.FACE_ACQUIRED_TOO_LEFT;
- } else if (aidlAcquired == AcquiredInfo.POOR_GAZE) {
- return BiometricFaceConstants.FACE_ACQUIRED_POOR_GAZE;
- } else if (aidlAcquired == AcquiredInfo.NOT_DETECTED) {
- return BiometricFaceConstants.FACE_ACQUIRED_NOT_DETECTED;
- } else if (aidlAcquired == AcquiredInfo.TOO_MUCH_MOTION) {
- return BiometricFaceConstants.FACE_ACQUIRED_TOO_MUCH_MOTION;
- } else if (aidlAcquired == AcquiredInfo.RECALIBRATE) {
- return BiometricFaceConstants.FACE_ACQUIRED_RECALIBRATE;
- } else if (aidlAcquired == AcquiredInfo.TOO_DIFFERENT) {
- return BiometricFaceConstants.FACE_ACQUIRED_TOO_DIFFERENT;
- } else if (aidlAcquired == AcquiredInfo.TOO_SIMILAR) {
- return BiometricFaceConstants.FACE_ACQUIRED_TOO_SIMILAR;
- } else if (aidlAcquired == AcquiredInfo.PAN_TOO_EXTREME) {
- return BiometricFaceConstants.FACE_ACQUIRED_PAN_TOO_EXTREME;
- } else if (aidlAcquired == AcquiredInfo.TILT_TOO_EXTREME) {
- return BiometricFaceConstants.FACE_ACQUIRED_TILT_TOO_EXTREME;
- } else if (aidlAcquired == AcquiredInfo.ROLL_TOO_EXTREME) {
- return BiometricFaceConstants.FACE_ACQUIRED_ROLL_TOO_EXTREME;
- } else if (aidlAcquired == AcquiredInfo.FACE_OBSCURED) {
- return BiometricFaceConstants.FACE_ACQUIRED_FACE_OBSCURED;
- } else if (aidlAcquired == AcquiredInfo.START) {
- return BiometricFaceConstants.FACE_ACQUIRED_START;
- } else if (aidlAcquired == AcquiredInfo.SENSOR_DIRTY) {
- return BiometricFaceConstants.FACE_ACQUIRED_SENSOR_DIRTY;
- } else if (aidlAcquired == AcquiredInfo.VENDOR) {
- return BiometricFaceConstants.FACE_ACQUIRED_VENDOR;
- } else if (aidlAcquired == AcquiredInfo.FIRST_FRAME_RECEIVED) {
- // No framework constant available
- return BiometricFaceConstants.FACE_ACQUIRED_UNKNOWN;
- } else if (aidlAcquired == AcquiredInfo.DARK_GLASSES_DETECTED) {
- // No framework constant available
- return BiometricFaceConstants.FACE_ACQUIRED_UNKNOWN;
- } else if (aidlAcquired == AcquiredInfo.MOUTH_COVERING_DETECTED) {
- // No framework constant available
- return BiometricFaceConstants.FACE_ACQUIRED_UNKNOWN;
- } else {
- return BiometricFaceConstants.FACE_ACQUIRED_UNKNOWN;
+ @BiometricFaceConstants.FaceAcquired
+ public static int toFrameworkAcquiredInfo(byte aidlAcquiredInfo) {
+ switch (aidlAcquiredInfo) {
+ case AcquiredInfo.GOOD:
+ return BiometricFaceConstants.FACE_ACQUIRED_GOOD;
+ case AcquiredInfo.INSUFFICIENT:
+ return BiometricFaceConstants.FACE_ACQUIRED_INSUFFICIENT;
+ case AcquiredInfo.TOO_BRIGHT:
+ return BiometricFaceConstants.FACE_ACQUIRED_TOO_BRIGHT;
+ case AcquiredInfo.TOO_DARK:
+ return BiometricFaceConstants.FACE_ACQUIRED_TOO_DARK;
+ case AcquiredInfo.TOO_CLOSE:
+ return BiometricFaceConstants.FACE_ACQUIRED_TOO_CLOSE;
+ case AcquiredInfo.TOO_FAR:
+ return BiometricFaceConstants.FACE_ACQUIRED_TOO_FAR;
+ case AcquiredInfo.FACE_TOO_HIGH:
+ return BiometricFaceConstants.FACE_ACQUIRED_TOO_HIGH;
+ case AcquiredInfo.FACE_TOO_LOW:
+ return BiometricFaceConstants.FACE_ACQUIRED_TOO_LOW;
+ case AcquiredInfo.FACE_TOO_RIGHT:
+ return BiometricFaceConstants.FACE_ACQUIRED_TOO_RIGHT;
+ case AcquiredInfo.FACE_TOO_LEFT:
+ return BiometricFaceConstants.FACE_ACQUIRED_TOO_LEFT;
+ case AcquiredInfo.POOR_GAZE:
+ return BiometricFaceConstants.FACE_ACQUIRED_POOR_GAZE;
+ case AcquiredInfo.NOT_DETECTED:
+ return BiometricFaceConstants.FACE_ACQUIRED_NOT_DETECTED;
+ case AcquiredInfo.TOO_MUCH_MOTION:
+ return BiometricFaceConstants.FACE_ACQUIRED_TOO_MUCH_MOTION;
+ case AcquiredInfo.RECALIBRATE:
+ return BiometricFaceConstants.FACE_ACQUIRED_RECALIBRATE;
+ case AcquiredInfo.TOO_DIFFERENT:
+ return BiometricFaceConstants.FACE_ACQUIRED_TOO_DIFFERENT;
+ case AcquiredInfo.TOO_SIMILAR:
+ return BiometricFaceConstants.FACE_ACQUIRED_TOO_SIMILAR;
+ case AcquiredInfo.PAN_TOO_EXTREME:
+ return BiometricFaceConstants.FACE_ACQUIRED_PAN_TOO_EXTREME;
+ case AcquiredInfo.TILT_TOO_EXTREME:
+ return BiometricFaceConstants.FACE_ACQUIRED_TILT_TOO_EXTREME;
+ case AcquiredInfo.ROLL_TOO_EXTREME:
+ return BiometricFaceConstants.FACE_ACQUIRED_ROLL_TOO_EXTREME;
+ case AcquiredInfo.FACE_OBSCURED:
+ return BiometricFaceConstants.FACE_ACQUIRED_FACE_OBSCURED;
+ case AcquiredInfo.START:
+ return BiometricFaceConstants.FACE_ACQUIRED_START;
+ case AcquiredInfo.SENSOR_DIRTY:
+ return BiometricFaceConstants.FACE_ACQUIRED_SENSOR_DIRTY;
+ case AcquiredInfo.VENDOR:
+ return BiometricFaceConstants.FACE_ACQUIRED_VENDOR;
+ case AcquiredInfo.UNKNOWN:
+ case AcquiredInfo.FIRST_FRAME_RECEIVED:
+ case AcquiredInfo.DARK_GLASSES_DETECTED:
+ case AcquiredInfo.MOUTH_COVERING_DETECTED:
+ default:
+ return BiometricFaceConstants.FACE_ACQUIRED_UNKNOWN;
+ }
+ }
+
+ @FaceEnrollStage
+ public static int toFrameworkEnrollmentStage(int aidlEnrollmentStage) {
+ switch (aidlEnrollmentStage) {
+ case EnrollmentStage.FIRST_FRAME_RECEIVED:
+ return FaceEnrollStages.FIRST_FRAME_RECEIVED;
+ case EnrollmentStage.WAITING_FOR_CENTERING:
+ return FaceEnrollStages.WAITING_FOR_CENTERING;
+ case EnrollmentStage.HOLD_STILL_IN_CENTER:
+ return FaceEnrollStages.HOLD_STILL_IN_CENTER;
+ case EnrollmentStage.ENROLLING_MOVEMENT_1:
+ return FaceEnrollStages.ENROLLING_MOVEMENT_1;
+ case EnrollmentStage.ENROLLING_MOVEMENT_2:
+ return FaceEnrollStages.ENROLLING_MOVEMENT_2;
+ case EnrollmentStage.ENROLLMENT_FINISHED:
+ return FaceEnrollStages.ENROLLMENT_FINISHED;
+ case EnrollmentStage.UNKNOWN:
+ default:
+ return FaceEnrollStages.UNKNOWN;
}
}
@@ -135,7 +153,9 @@
@NonNull
public static FaceEnrollFrame toFrameworkEnrollmentFrame(@NonNull EnrollmentFrame frame) {
- return new FaceEnrollFrame(toFrameworkCell(frame.cell), frame.stage,
+ return new FaceEnrollFrame(
+ toFrameworkCell(frame.cell),
+ toFrameworkEnrollmentStage(frame.stage),
toFrameworkBaseFrame(frame.data));
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceGenerateChallengeClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceGenerateChallengeClient.java
index 8cbb896..5804622 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceGenerateChallengeClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceGenerateChallengeClient.java
@@ -45,6 +45,7 @@
getFreshDaemon().generateChallenge();
} catch (RemoteException e) {
Slog.e(TAG, "Unable to generateChallenge", e);
+ mCallback.onClientFinished(this, false /* success */);
}
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceRevokeChallengeClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceRevokeChallengeClient.java
index 2294173..99bf893 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceRevokeChallengeClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceRevokeChallengeClient.java
@@ -48,6 +48,7 @@
getFreshDaemon().revokeChallenge(mChallenge);
} catch (RemoteException e) {
Slog.e(TAG, "Unable to revokeChallenge", e);
+ mCallback.onClientFinished(this, false /* success */);
}
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceGenerateChallengeClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceGenerateChallengeClient.java
index 72c5ee5..24af817 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceGenerateChallengeClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceGenerateChallengeClient.java
@@ -67,6 +67,7 @@
}
} catch (RemoteException e) {
Slog.e(TAG, "generateChallenge failed", e);
+ mCallback.onClientFinished(this, false /* success */);
}
}
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceRevokeChallengeClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceRevokeChallengeClient.java
index 28580de..ff3e770 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceRevokeChallengeClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceRevokeChallengeClient.java
@@ -43,8 +43,10 @@
protected void startHalOperation() {
try {
getFreshDaemon().revokeChallenge();
+ mCallback.onClientFinished(this, true /* success */);
} catch (RemoteException e) {
Slog.e(TAG, "revokeChallenge failed", e);
+ mCallback.onClientFinished(this, false /* success */);
}
}
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintGenerateChallengeClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintGenerateChallengeClient.java
index 83c6421..15a85e6 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintGenerateChallengeClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintGenerateChallengeClient.java
@@ -47,18 +47,17 @@
getFreshDaemon().generateChallenge();
} catch (RemoteException e) {
Slog.e(TAG, "Unable to generateChallenge", e);
+ mCallback.onClientFinished(this, false /* success */);
}
}
void onChallengeGenerated(int sensorId, int userId, long challenge) {
try {
getListener().onChallengeGenerated(sensorId, challenge);
- mCallback.onClientFinished(FingerprintGenerateChallengeClient.this,
- true /* success */);
+ mCallback.onClientFinished(this, true /* success */);
} catch (RemoteException e) {
Slog.e(TAG, "Unable to send challenge", e);
- mCallback.onClientFinished(FingerprintGenerateChallengeClient.this,
- false /* success */);
+ mCallback.onClientFinished(this, false /* success */);
}
}
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintRevokeChallengeClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintRevokeChallengeClient.java
index d9bf1c3..90c6978 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintRevokeChallengeClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintRevokeChallengeClient.java
@@ -48,6 +48,7 @@
getFreshDaemon().revokeChallenge(mChallenge);
} catch (RemoteException e) {
Slog.e(TAG, "Unable to revokeChallenge", e);
+ mCallback.onClientFinished(this, false /* success */);
}
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintGenerateChallengeClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintGenerateChallengeClient.java
index 5169c7d..302ec2b 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintGenerateChallengeClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintGenerateChallengeClient.java
@@ -55,6 +55,7 @@
}
} catch (RemoteException e) {
Slog.e(TAG, "preEnroll failed", e);
+ mCallback.onClientFinished(this, false /* success */);
}
}
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintRevokeChallengeClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintRevokeChallengeClient.java
index 8f58cae..93d8ff3 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintRevokeChallengeClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintRevokeChallengeClient.java
@@ -45,8 +45,10 @@
protected void startHalOperation() {
try {
getFreshDaemon().postEnroll();
+ mCallback.onClientFinished(this, true /* success */);
} catch (RemoteException e) {
Slog.e(TAG, "revokeChallenge/postEnroll failed", e);
+ mCallback.onClientFinished(this, false /* success */);
}
}
}
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index 91b96dc..1a07cb8 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -738,13 +738,19 @@
float value = mBrightnessMapper.getBrightness(mAmbientLux, mForegroundAppPackageName,
mForegroundAppCategory);
float newScreenAutoBrightness = clampScreenBrightness(value);
+
+ // The min/max range can change for brightness due to HBM. See if the current brightness
+ // value still falls within the current range (which could have changed).
+ final boolean currentBrightnessWithinAllowedRange = BrightnessSynchronizer.floatEquals(
+ mScreenAutoBrightness, clampScreenBrightness(mScreenAutoBrightness));
// If screenAutoBrightness is set, we should have screen{Brightening,Darkening}Threshold,
// in which case we ignore the new screen brightness if it doesn't differ enough from the
// previous one.
if (!Float.isNaN(mScreenAutoBrightness)
&& !isManuallySet
&& newScreenAutoBrightness > mScreenDarkeningThreshold
- && newScreenAutoBrightness < mScreenBrighteningThreshold) {
+ && newScreenAutoBrightness < mScreenBrighteningThreshold
+ && currentBrightnessWithinAllowedRange) {
if (mLoggingEnabled) {
Slog.d(TAG, "ignoring newScreenAutoBrightness: "
+ mScreenDarkeningThreshold + " < " + newScreenAutoBrightness
diff --git a/services/core/java/com/android/server/display/DisplayBlanker.java b/services/core/java/com/android/server/display/DisplayBlanker.java
index e2129ba..8de49af 100644
--- a/services/core/java/com/android/server/display/DisplayBlanker.java
+++ b/services/core/java/com/android/server/display/DisplayBlanker.java
@@ -20,5 +20,8 @@
* Interface used to update the actual display state.
*/
public interface DisplayBlanker {
- void requestDisplayState(int displayId, int state, float brightness);
+ /**
+ * Requests the specified display state and brightness levels for the specified displayId.
+ */
+ void requestDisplayState(int displayId, int state, float brightness, float sdrBrightness);
}
diff --git a/services/core/java/com/android/server/display/DisplayDevice.java b/services/core/java/com/android/server/display/DisplayDevice.java
index b3070b7..35f2957 100644
--- a/services/core/java/com/android/server/display/DisplayDevice.java
+++ b/services/core/java/com/android/server/display/DisplayDevice.java
@@ -156,10 +156,12 @@
*
* @param state The new display state.
* @param brightnessState The new display brightnessState.
+ * @param sdrBrightnessState The new display brightnessState for SDR layers.
* @return A runnable containing work to be deferred until after we have
* exited the critical section, or null if none.
*/
- public Runnable requestDisplayStateLocked(int state, float brightnessState) {
+ public Runnable requestDisplayStateLocked(int state, float brightnessState,
+ float sdrBrightnessState) {
return null;
}
diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
index 2d7145f..c46cfe3 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
@@ -104,6 +104,7 @@
private float mBrightnessRampSlowIncrease = Float.NaN;
private Spline mBrightnessToBacklightSpline;
private Spline mBacklightToBrightnessSpline;
+ private Spline mBacklightToNitsSpline;
private List<String> mQuirks;
private boolean mIsHighBrightnessModeEnabled = false;
private HighBrightnessModeData mHbmData;
@@ -219,6 +220,20 @@
}
/**
+ * Calculates the nits value for the specified backlight value if a mapping exists.
+ *
+ * @return The mapped nits or 0 if no mapping exits.
+ */
+ public float getNitsFromBacklight(float backlight) {
+ if (mBacklightToNitsSpline == null) {
+ Slog.wtf(TAG, "requesting nits when no mapping exists.");
+ return -1;
+ }
+ backlight = Math.max(backlight, mBacklightMinimum);
+ return mBacklightToNitsSpline.interpolate(backlight);
+ }
+
+ /**
* Return an array of equal length to backlight and nits, that covers the entire system
* brightness range of 0.0-1.0.
*
@@ -258,6 +273,13 @@
}
/**
+ * @return true if a nits to backlight mapping is defined in this config, false otherwise.
+ */
+ public boolean hasNitsMapping() {
+ return mBacklightToNitsSpline != null;
+ }
+
+ /**
* @param quirkValue The quirk to test.
* @return {@code true} if the specified quirk is present in this configuration,
* {@code false} otherwise.
@@ -584,6 +606,7 @@
}
mBrightnessToBacklightSpline = Spline.createSpline(mBrightness, mBacklight);
mBacklightToBrightnessSpline = Spline.createSpline(mBacklight, mBrightness);
+ mBacklightToNitsSpline = Spline.createSpline(mBacklight, mNits);
}
private void loadQuirks(DisplayConfiguration config) {
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 789f08f..0a4b137 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -257,7 +257,8 @@
private final DisplayBlanker mDisplayBlanker = new DisplayBlanker() {
// Synchronized to avoid race conditions when updating multiple display states.
@Override
- public synchronized void requestDisplayState(int displayId, int state, float brightness) {
+ public synchronized void requestDisplayState(int displayId, int state, float brightness,
+ float sdrBrightness) {
boolean allInactive = true;
boolean allOff = true;
final boolean stateChanged;
@@ -288,7 +289,7 @@
// The order of operations is important for legacy reasons.
if (state == Display.STATE_OFF) {
- requestDisplayStateInternal(displayId, state, brightness);
+ requestDisplayStateInternal(displayId, state, brightness, sdrBrightness);
}
if (stateChanged) {
@@ -296,7 +297,7 @@
}
if (state != Display.STATE_OFF) {
- requestDisplayStateInternal(displayId, state, brightness);
+ requestDisplayStateInternal(displayId, state, brightness, sdrBrightness);
}
}
};
@@ -316,7 +317,7 @@
// A map from LogicalDisplay ID to display brightness.
@GuardedBy("mSyncRoot")
- private final SparseArray<Float> mDisplayBrightnesses = new SparseArray<>();
+ private final SparseArray<BrightnessPair> mDisplayBrightnesses = new SparseArray<>();
// Set to true when there are pending display changes that have yet to be applied
// to the surface flinger state.
@@ -667,11 +668,8 @@
}
}
- private void requestDisplayStateInternal(int displayId, int state, float brightnessState) {
- if (state == Display.STATE_UNKNOWN) {
- state = Display.STATE_ON;
- }
- if (state == Display.STATE_OFF) {
+ private float clampBrightness(int displayState, float brightnessState) {
+ if (displayState == Display.STATE_OFF) {
brightnessState = PowerManager.BRIGHTNESS_OFF_FLOAT;
} else if (brightnessState != PowerManager.BRIGHTNESS_OFF_FLOAT
&& brightnessState < PowerManager.BRIGHTNESS_MIN) {
@@ -679,6 +677,17 @@
} else if (brightnessState > PowerManager.BRIGHTNESS_MAX) {
brightnessState = PowerManager.BRIGHTNESS_MAX;
}
+ return brightnessState;
+ }
+
+ private void requestDisplayStateInternal(int displayId, int state, float brightnessState,
+ float sdrBrightnessState) {
+ if (state == Display.STATE_UNKNOWN) {
+ state = Display.STATE_ON;
+ }
+
+ brightnessState = clampBrightness(state, brightnessState);
+ sdrBrightnessState = clampBrightness(state, sdrBrightnessState);
// Update the display state within the lock.
// Note that we do not need to schedule traversals here although it
@@ -688,20 +697,26 @@
synchronized (mSyncRoot) {
final int index = mDisplayStates.indexOfKey(displayId);
+ final BrightnessPair brightnessPair =
+ index < 0 ? null : mDisplayBrightnesses.valueAt(index);
if (index < 0 || (mDisplayStates.valueAt(index) == state
- && BrightnessSynchronizer.floatEquals(mDisplayBrightnesses.valueAt(index),
- brightnessState))) {
+ && BrightnessSynchronizer.floatEquals(
+ brightnessPair.brightness, brightnessState)
+ && BrightnessSynchronizer.floatEquals(
+ brightnessPair.sdrBrightness, sdrBrightnessState))) {
return; // Display no longer exists or no change.
}
traceMessage = "requestDisplayStateInternal("
+ displayId + ", "
+ Display.stateToString(state)
- + ", brightness=" + brightnessState + ")";
+ + ", brightness=" + brightnessState
+ + ", sdrBrightness=" + sdrBrightnessState + ")";
Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, traceMessage, displayId);
mDisplayStates.setValueAt(index, state);
- mDisplayBrightnesses.setValueAt(index, brightnessState);
+ brightnessPair.brightness = brightnessState;
+ brightnessPair.sdrBrightness = sdrBrightnessState;
runnable = updateDisplayStateLocked(mLogicalDisplayMapper.getDisplayLocked(displayId)
.getPrimaryDisplayDeviceLocked());
}
@@ -1235,7 +1250,9 @@
addDisplayPowerControllerLocked(display);
mDisplayStates.append(displayId, Display.STATE_UNKNOWN);
- mDisplayBrightnesses.append(displayId, display.getDisplayInfoLocked().brightnessDefault);
+ final float brightnessDefault = display.getDisplayInfoLocked().brightnessDefault;
+ mDisplayBrightnesses.append(displayId,
+ new BrightnessPair(brightnessDefault, brightnessDefault));
DisplayManagerGlobal.invalidateLocalDisplayInfoCaches();
@@ -1265,11 +1282,6 @@
// this point.
sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
scheduleTraversalLocked(false);
-
- DisplayPowerController dpc = mDisplayPowerControllers.get(displayId);
- if (dpc != null) {
- dpc.onDisplayChanged();
- }
}
private void handleLogicalDisplayFrameRateOverridesChangedLocked(
@@ -1301,6 +1313,11 @@
if (work != null) {
mHandler.post(work);
}
+ final int displayId = display.getDisplayIdLocked();
+ DisplayPowerController dpc = mDisplayPowerControllers.get(displayId);
+ if (dpc != null) {
+ dpc.onDisplayChanged();
+ }
handleLogicalDisplayChangedLocked(display);
}
@@ -1326,8 +1343,9 @@
// Only send a request for display state if display state has already been initialized.
if (state != Display.STATE_UNKNOWN) {
- final float brightness = mDisplayBrightnesses.get(displayId);
- return device.requestDisplayStateLocked(state, brightness);
+ final BrightnessPair brightnessPair = mDisplayBrightnesses.get(displayId);
+ return device.requestDisplayStateLocked(state, brightnessPair.brightness,
+ brightnessPair.sdrBrightness);
}
}
return null;
@@ -1935,10 +1953,11 @@
for (int i = 0; i < displayStateCount; i++) {
final int displayId = mDisplayStates.keyAt(i);
final int displayState = mDisplayStates.valueAt(i);
- final float brightness = mDisplayBrightnesses.valueAt(i);
+ final BrightnessPair brightnessPair = mDisplayBrightnesses.valueAt(i);
pw.println(" Display Id=" + displayId);
pw.println(" Display State=" + Display.stateToString(displayState));
- pw.println(" Display Brightness=" + brightness);
+ pw.println(" Display Brightness=" + brightnessPair.brightness);
+ pw.println(" Display SdrBrightness=" + brightnessPair.sdrBrightness);
}
IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
@@ -3277,6 +3296,16 @@
}
};
+ private class BrightnessPair {
+ public float brightness;
+ public float sdrBrightness;
+
+ BrightnessPair(float brightness, float sdrBrightness) {
+ this.brightness = brightness;
+ this.sdrBrightness = sdrBrightness;
+ }
+ }
+
/**
* Functional interface for providing time.
* TODO(b/184781936): merge with PowerManagerService.Clock
@@ -3288,5 +3317,4 @@
*/
long uptimeMillis();
}
-
}
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 3340e3c..7a50a34 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -38,6 +38,7 @@
import android.metrics.LogMaker;
import android.net.Uri;
import android.os.Handler;
+import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
@@ -61,6 +62,7 @@
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.server.LocalServices;
import com.android.server.am.BatteryStatsService;
+import com.android.server.display.RampAnimator.DualRampAnimator;
import com.android.server.display.color.ColorDisplayService.ColorDisplayServiceInternal;
import com.android.server.display.color.ColorDisplayService.ReduceBrightColorsListener;
import com.android.server.display.whitebalance.DisplayWhiteBalanceController;
@@ -223,6 +225,8 @@
@GuardedBy("mCachedBrightnessInfo")
private final CachedBrightnessInfo mCachedBrightnessInfo = new CachedBrightnessInfo();
+ private DisplayDevice mDisplayDevice;
+
// True if we should fade the screen while turning it off, false if we should play
// a stylish color fade animation instead.
private boolean mColorFadeFadesConfig;
@@ -424,7 +428,7 @@
// Animators.
private ObjectAnimator mColorFadeOnAnimator;
private ObjectAnimator mColorFadeOffAnimator;
- private RampAnimator<DisplayPowerState> mScreenBrightnessRampAnimator;
+ private DualRampAnimator<DisplayPowerState> mScreenBrightnessRampAnimator;
private BrightnessSetting.BrightnessSettingListener mBrightnessSettingListener;
// True if this DisplayPowerController has been stopped and should no longer be running.
@@ -442,6 +446,7 @@
Runnable onBrightnessChangeRunnable) {
mLogicalDisplay = logicalDisplay;
mDisplayId = mLogicalDisplay.getDisplayIdLocked();
+ mDisplayDevice = mLogicalDisplay.getPrimaryDisplayDeviceLocked();
mHandler = new DisplayControllerHandler(handler.getLooper());
if (mDisplayId == Display.DEFAULT_DISPLAY) {
@@ -780,12 +785,29 @@
* when displays get swapped on foldable devices. For example, different brightness properties
* of each display need to be properly reflected in AutomaticBrightnessController.
*/
+ @GuardedBy("DisplayManagerService.mSyncRoot")
public void onDisplayChanged() {
- // TODO: b/175821789 - Support high brightness on multiple (folding) displays
- mUniqueDisplayId = mLogicalDisplay.getPrimaryDisplayDeviceLocked().getUniqueId();
- mDisplayDeviceConfig = mLogicalDisplay.getPrimaryDisplayDeviceLocked()
- .getDisplayDeviceConfig();
- loadAmbientLightSensor();
+ final DisplayDevice device = mLogicalDisplay.getPrimaryDisplayDeviceLocked();
+ if (device == null) {
+ Slog.wtf(TAG, "Display Device is null in DisplayPowerController for display: "
+ + mLogicalDisplay.getDisplayIdLocked());
+ return;
+ }
+
+ final String uniqueId = device.getUniqueId();
+ final DisplayDeviceConfig config = device.getDisplayDeviceConfig();
+ final IBinder token = device.getDisplayTokenLocked();
+ mHandler.post(() -> {
+ if (mDisplayDevice == device) {
+ return;
+ }
+ mDisplayDevice = device;
+ mUniqueDisplayId = uniqueId;
+ mDisplayDeviceConfig = config;
+
+ loadAmbientLightSensor();
+ mHbmController.resetHbmData(token, config.getHighBrightnessModeData());
+ });
}
/**
@@ -855,8 +877,9 @@
mColorFadeOffAnimator.addListener(mAnimatorListener);
}
- mScreenBrightnessRampAnimator = new RampAnimator<>(
- mPowerState, DisplayPowerState.SCREEN_BRIGHTNESS_FLOAT);
+ mScreenBrightnessRampAnimator = new DualRampAnimator<>(mPowerState,
+ DisplayPowerState.SCREEN_BRIGHTNESS_FLOAT,
+ DisplayPowerState.SCREEN_SDR_BRIGHTNESS_FLOAT);
mScreenBrightnessRampAnimator.setListener(mRampAnimatorListener);
noteScreenState(mPowerState.getScreenState());
@@ -902,6 +925,7 @@
/** Clean up all resources that are accessed via the {@link #mHandler} thread. */
private void cleanupHandlerThreadAfterStop() {
setProximitySensorEnabled(false);
+ mHbmController.stop();
mHandler.removeCallbacksAndMessages(null);
if (mUnfinishedBusiness) {
mCallbacks.releaseSuspendBlocker();
@@ -1205,9 +1229,10 @@
// timeout is about to expire.
if (mPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {
if (brightnessState > PowerManager.BRIGHTNESS_MIN) {
- brightnessState = Math.max(Math.min(brightnessState
- - SCREEN_DIM_MINIMUM_REDUCTION_FLOAT,
- mScreenBrightnessDimConfig), PowerManager.BRIGHTNESS_MIN);
+ brightnessState = Math.max(
+ Math.min(brightnessState - SCREEN_DIM_MINIMUM_REDUCTION_FLOAT,
+ mScreenBrightnessDimConfig),
+ PowerManager.BRIGHTNESS_MIN);
mBrightnessReasonTemp.addModifier(BrightnessReason.MODIFIER_DIMMED);
}
if (!mAppliedDimming) {
@@ -1282,12 +1307,27 @@
// transformations to the brightness have pushed it outside of the currently
// allowed range.
float animateValue = clampScreenBrightness(brightnessState);
+
+ // If there are any HDR layers on the screen, we have a special brightness value that we
+ // use instead. We still preserve the calculated brightness for Standard Dynamic Range
+ // (SDR) layers, but the main brightness value will be the one for HDR.
+ float sdrAnimateValue = animateValue;
+ if (mHbmController.getHighBrightnessMode() == BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR
+ && ((mBrightnessReason.modifier & BrightnessReason.MODIFIER_DIMMED) == 0
+ || (mBrightnessReason.modifier & BrightnessReason.MODIFIER_LOW_POWER) == 0)) {
+ animateValue = mHbmController.getHdrBrightnessValue();
+ }
+
final float currentBrightness = mPowerState.getScreenBrightness();
+ final float currentSdrBrightness = mPowerState.getSdrScreenBrightness();
if (isValidBrightnessValue(animateValue)
- && !BrightnessSynchronizer.floatEquals(animateValue, currentBrightness)) {
+ && (!BrightnessSynchronizer.floatEquals(animateValue, currentBrightness)
+ || !BrightnessSynchronizer.floatEquals(
+ sdrAnimateValue, currentSdrBrightness))) {
if (initialRampSkip || hasBrightnessBuckets
|| wasOrWillBeInVr || !isDisplayContentVisible || brightnessIsTemporary) {
- animateScreenBrightness(animateValue, SCREEN_ANIMATION_RATE_MINIMUM);
+ animateScreenBrightness(animateValue, sdrAnimateValue,
+ SCREEN_ANIMATION_RATE_MINIMUM);
} else {
boolean isIncreasing = animateValue > currentBrightness;
final float rampSpeed;
@@ -1300,7 +1340,7 @@
} else {
rampSpeed = mBrightnessRampRateFastDecrease;
}
- animateScreenBrightness(animateValue, rampSpeed);
+ animateScreenBrightness(animateValue, sdrAnimateValue, rampSpeed);
}
}
@@ -1446,9 +1486,11 @@
private HighBrightnessModeController createHbmController() {
final DisplayDeviceConfig ddConfig =
mLogicalDisplay.getPrimaryDisplayDeviceLocked().getDisplayDeviceConfig();
+ final IBinder displayToken =
+ mLogicalDisplay.getPrimaryDisplayDeviceLocked().getDisplayTokenLocked();
final DisplayDeviceConfig.HighBrightnessModeData hbmData =
ddConfig != null ? ddConfig.getHighBrightnessModeData() : null;
- return new HighBrightnessModeController(mHandler, PowerManager.BRIGHTNESS_MIN,
+ return new HighBrightnessModeController(mHandler, displayToken, PowerManager.BRIGHTNESS_MIN,
PowerManager.BRIGHTNESS_MAX, hbmData,
() -> {
sendUpdatePowerStateLocked();
@@ -1596,11 +1638,12 @@
&& brightnessState <= PowerManager.BRIGHTNESS_MAX;
}
- private void animateScreenBrightness(float target, float rate) {
+ private void animateScreenBrightness(float target, float sdrTarget, float rate) {
if (DEBUG) {
- Slog.d(TAG, "Animating brightness: target=" + target +", rate=" + rate);
+ Slog.d(TAG, "Animating brightness: target=" + target + ", sdrTarget=" + sdrTarget
+ + ", rate=" + rate);
}
- if (mScreenBrightnessRampAnimator.animateTo(target, rate)) {
+ if (mScreenBrightnessRampAnimator.animateTo(target, sdrTarget, rate)) {
Trace.traceCounter(Trace.TRACE_TAG_POWER, "TargetScreenBrightness", (int) target);
// TODO(b/153319140) remove when we can get this from the above trace invocation
SystemProperties.set("debug.tracing.screen_brightness", String.valueOf(target));
@@ -2295,6 +2338,7 @@
return;
}
handleSettingsChange(false /*userSwitch*/);
+ break;
}
}
}
@@ -2392,7 +2436,8 @@
static final int MODIFIER_DIMMED = 0x1;
static final int MODIFIER_LOW_POWER = 0x2;
- static final int MODIFIER_MASK = 0x3;
+ static final int MODIFIER_HDR = 0x4;
+ static final int MODIFIER_MASK = MODIFIER_DIMMED | MODIFIER_LOW_POWER | MODIFIER_HDR;
// ADJUSTMENT_*
// These things can happen at any point, even if the main brightness reason doesn't
@@ -2464,6 +2509,9 @@
if ((modifier & MODIFIER_DIMMED) != 0) {
sb.append(" dim");
}
+ if ((modifier & MODIFIER_HDR) != 0) {
+ sb.append(" hdr");
+ }
int strlen = sb.length();
if (sb.charAt(strlen - 1) == '[') {
sb.setLength(strlen - 2);
diff --git a/services/core/java/com/android/server/display/DisplayPowerState.java b/services/core/java/com/android/server/display/DisplayPowerState.java
index 77aff5b..b58dd38 100644
--- a/services/core/java/com/android/server/display/DisplayPowerState.java
+++ b/services/core/java/com/android/server/display/DisplayPowerState.java
@@ -62,6 +62,7 @@
private int mScreenState;
private float mScreenBrightness;
+ private float mSdrScreenBrightness;
private boolean mScreenReady;
private boolean mScreenUpdatePending;
@@ -92,6 +93,7 @@
mScreenState = displayState;
mScreenBrightness = (displayState != Display.STATE_OFF) ? PowerManager.BRIGHTNESS_MAX
: PowerManager.BRIGHTNESS_OFF_FLOAT;
+ mSdrScreenBrightness = mScreenBrightness;
scheduleScreenUpdate();
mColorFadePrepared = false;
@@ -126,6 +128,19 @@
}
};
+ public static final FloatProperty<DisplayPowerState> SCREEN_SDR_BRIGHTNESS_FLOAT =
+ new FloatProperty<DisplayPowerState>("sdrScreenBrightnessFloat") {
+ @Override
+ public void setValue(DisplayPowerState object, float value) {
+ object.setSdrScreenBrightness(value);
+ }
+
+ @Override
+ public Float get(DisplayPowerState object) {
+ return object.getSdrScreenBrightness();
+ }
+ };
+
/**
* Sets whether the screen is on, off, or dozing.
*/
@@ -149,12 +164,38 @@
}
/**
+ * Sets the display's SDR brightness.
+ *
+ * @param brightness The brightness, ranges from 0.0f (minimum / off) to 1.0f (brightest).
+ */
+ public void setSdrScreenBrightness(float brightness) {
+ if (!BrightnessSynchronizer.floatEquals(mSdrScreenBrightness, brightness)) {
+ if (DEBUG) {
+ Slog.d(TAG, "setSdrScreenBrightness: brightness=" + brightness);
+ }
+
+ mSdrScreenBrightness = brightness;
+ if (mScreenState != Display.STATE_OFF) {
+ mScreenReady = false;
+ scheduleScreenUpdate();
+ }
+ }
+ }
+
+ /**
+ * Gets the screen SDR brightness.
+ */
+ public float getSdrScreenBrightness() {
+ return mSdrScreenBrightness;
+ }
+
+ /**
* Sets the display brightness.
*
* @param brightness The brightness, ranges from 0.0f (minimum / off) to 1.0f (brightest).
*/
public void setScreenBrightness(float brightness) {
- if (mScreenBrightness != brightness) {
+ if (!BrightnessSynchronizer.floatEquals(mScreenBrightness, brightness)) {
if (DEBUG) {
Slog.d(TAG, "setScreenBrightness: brightness=" + brightness);
}
@@ -286,6 +327,7 @@
pw.println(" mStopped=" + mStopped);
pw.println(" mScreenState=" + Display.stateToString(mScreenState));
pw.println(" mScreenBrightness=" + mScreenBrightness);
+ pw.println(" mSdrScreenBrightness=" + mSdrScreenBrightness);
pw.println(" mScreenReady=" + mScreenReady);
pw.println(" mScreenUpdatePending=" + mScreenUpdatePending);
pw.println(" mColorFadePrepared=" + mColorFadePrepared);
@@ -332,7 +374,10 @@
float brightnessState = mScreenState != Display.STATE_OFF
&& mColorFadeLevel > 0f ? mScreenBrightness : PowerManager.BRIGHTNESS_OFF_FLOAT;
- if (mPhotonicModulator.setState(mScreenState, brightnessState)) {
+ float sdrBrightnessState = mScreenState != Display.STATE_OFF
+ && mColorFadeLevel > 0f
+ ? mSdrScreenBrightness : PowerManager.BRIGHTNESS_OFF_FLOAT;
+ if (mPhotonicModulator.setState(mScreenState, brightnessState, sdrBrightnessState)) {
if (DEBUG) {
Slog.d(TAG, "Screen ready");
}
@@ -373,8 +418,10 @@
private int mPendingState = INITIAL_SCREEN_STATE;
private float mPendingBacklight = INITIAL_BACKLIGHT_FLOAT;
+ private float mPendingSdrBacklight = INITIAL_BACKLIGHT_FLOAT;
private int mActualState = INITIAL_SCREEN_STATE;
private float mActualBacklight = INITIAL_BACKLIGHT_FLOAT;
+ private float mActualSdrBacklight = INITIAL_BACKLIGHT_FLOAT;
private boolean mStateChangeInProgress;
private boolean mBacklightChangeInProgress;
@@ -382,11 +429,13 @@
super("PhotonicModulator");
}
- public boolean setState(int state, float brightnessState) {
+ public boolean setState(int state, float brightnessState, float sdrBrightnessState) {
synchronized (mLock) {
boolean stateChanged = state != mPendingState;
- boolean backlightChanged = !BrightnessSynchronizer.floatEquals(
- brightnessState, mPendingBacklight);
+ boolean backlightChanged =
+ !BrightnessSynchronizer.floatEquals(brightnessState, mPendingBacklight)
+ || !BrightnessSynchronizer.floatEquals(
+ sdrBrightnessState, mPendingSdrBacklight);
if (stateChanged || backlightChanged) {
if (DEBUG) {
Slog.d(TAG, "Requesting new screen state: state="
@@ -395,6 +444,7 @@
mPendingState = state;
mPendingBacklight = brightnessState;
+ mPendingSdrBacklight = sdrBrightnessState;
boolean changeInProgress = mStateChangeInProgress || mBacklightChangeInProgress;
mStateChangeInProgress = stateChanged || mStateChangeInProgress;
mBacklightChangeInProgress = backlightChanged || mBacklightChangeInProgress;
@@ -413,8 +463,10 @@
pw.println("Photonic Modulator State:");
pw.println(" mPendingState=" + Display.stateToString(mPendingState));
pw.println(" mPendingBacklight=" + mPendingBacklight);
+ pw.println(" mPendingSdrBacklight=" + mPendingSdrBacklight);
pw.println(" mActualState=" + Display.stateToString(mActualState));
pw.println(" mActualBacklight=" + mActualBacklight);
+ pw.println(" mActualSdrBacklight=" + mActualSdrBacklight);
pw.println(" mStateChangeInProgress=" + mStateChangeInProgress);
pw.println(" mBacklightChangeInProgress=" + mBacklightChangeInProgress);
}
@@ -427,13 +479,17 @@
final int state;
final boolean stateChanged;
final float brightnessState;
+ final float sdrBrightnessState;
final boolean backlightChanged;
synchronized (mLock) {
state = mPendingState;
stateChanged = (state != mActualState);
brightnessState = mPendingBacklight;
- backlightChanged = !BrightnessSynchronizer.floatEquals(
- brightnessState, mActualBacklight);
+ sdrBrightnessState = mPendingSdrBacklight;
+ backlightChanged =
+ !BrightnessSynchronizer.floatEquals(brightnessState, mActualBacklight)
+ || !BrightnessSynchronizer.floatEquals(
+ sdrBrightnessState, mActualSdrBacklight);
if (!stateChanged) {
// State changed applied, notify outer class.
postScreenUpdateThreadSafe();
@@ -454,14 +510,17 @@
}
mActualState = state;
mActualBacklight = brightnessState;
+ mActualSdrBacklight = sdrBrightnessState;
}
// Apply pending change.
if (DEBUG) {
Slog.d(TAG, "Updating screen state: id=" + mDisplayId + ", state="
- + Display.stateToString(state) + ", backlight=" + brightnessState);
+ + Display.stateToString(state) + ", backlight=" + brightnessState
+ + ", sdrBacklight=" + sdrBrightnessState);
}
- mBlanker.requestDisplayState(mDisplayId, state, brightnessState);
+ mBlanker.requestDisplayState(mDisplayId, state, brightnessState,
+ sdrBrightnessState);
}
}
}
diff --git a/services/core/java/com/android/server/display/HighBrightnessModeController.java b/services/core/java/com/android/server/display/HighBrightnessModeController.java
index e6486bd..b948777 100644
--- a/services/core/java/com/android/server/display/HighBrightnessModeController.java
+++ b/services/core/java/com/android/server/display/HighBrightnessModeController.java
@@ -18,9 +18,11 @@
import android.hardware.display.BrightnessInfo;
import android.os.Handler;
+import android.os.IBinder;
import android.os.PowerManager;
import android.os.SystemClock;
import android.util.Slog;
+import android.view.SurfaceControlHdrLayerInfoListener;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.display.DisplayDeviceConfig.HighBrightnessModeData;
@@ -45,17 +47,21 @@
private final float mBrightnessMin;
private final float mBrightnessMax;
- private final HighBrightnessModeData mHbmData;
private final Handler mHandler;
private final Runnable mHbmChangeCallback;
private final Runnable mRecalcRunnable;
private final Clock mClock;
+ private SurfaceControlHdrLayerInfoListener mHdrListener;
+ private HighBrightnessModeData mHbmData;
+ private IBinder mRegisteredDisplayToken;
+
private boolean mIsInAllowedAmbientRange = false;
private boolean mIsTimeAvailable = false;
private boolean mIsAutoBrightnessEnabled = false;
private float mAutoBrightness;
private int mHbmMode = BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF;
+ private boolean mIsHdrLayerPresent = false;
/**
* If HBM is currently running, this is the start time for the current HBM session.
@@ -69,23 +75,26 @@
*/
private LinkedList<HbmEvent> mEvents = new LinkedList<>();
- HighBrightnessModeController(Handler handler, float brightnessMin, float brightnessMax,
- HighBrightnessModeData hbmData, Runnable hbmChangeCallback) {
- this(SystemClock::uptimeMillis, handler, brightnessMin, brightnessMax, hbmData,
- hbmChangeCallback);
+ HighBrightnessModeController(Handler handler, IBinder displayToken, float brightnessMin,
+ float brightnessMax, HighBrightnessModeData hbmData, Runnable hbmChangeCallback) {
+ this(SystemClock::uptimeMillis, handler, displayToken, brightnessMin, brightnessMax,
+ hbmData, hbmChangeCallback);
}
@VisibleForTesting
- HighBrightnessModeController(Clock clock, Handler handler, float brightnessMin,
- float brightnessMax, HighBrightnessModeData hbmData, Runnable hbmChangeCallback) {
+ HighBrightnessModeController(Clock clock, Handler handler, IBinder displayToken,
+ float brightnessMin, float brightnessMax, HighBrightnessModeData hbmData,
+ Runnable hbmChangeCallback) {
mClock = clock;
mHandler = handler;
mBrightnessMin = brightnessMin;
mBrightnessMax = brightnessMax;
- mHbmData = hbmData;
mHbmChangeCallback = hbmChangeCallback;
mAutoBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
mRecalcRunnable = this::recalculateTimeAllowance;
+ mHdrListener = new HdrListener();
+
+ resetHbmData(displayToken, hbmData);
}
void setAutoBrightnessEnabled(boolean isEnabled) {
@@ -117,6 +126,10 @@
}
}
+ float getHdrBrightnessValue() {
+ return mBrightnessMax;
+ }
+
void onAmbientLuxChange(float ambientLux) {
if (!deviceSupportsHbm() || !mIsAutoBrightnessEnabled) {
return;
@@ -138,11 +151,12 @@
// If we are starting or ending a high brightness mode session, store the current
// session in mRunningStartTimeMillis, or the old one in mEvents.
- final boolean wasOldBrightnessHigh = oldAutoBrightness > mHbmData.transitionPoint;
- final boolean isNewBrightnessHigh = mAutoBrightness > mHbmData.transitionPoint;
- if (wasOldBrightnessHigh != isNewBrightnessHigh) {
+ final boolean wasHbmDrainingAvailableTime = mRunningStartTimeMillis != -1;
+ final boolean shouldHbmDrainAvailableTime = mAutoBrightness > mHbmData.transitionPoint
+ && !mIsHdrLayerPresent;
+ if (wasHbmDrainingAvailableTime != shouldHbmDrainAvailableTime) {
final long currentTime = mClock.uptimeMillis();
- if (isNewBrightnessHigh) {
+ if (shouldHbmDrainAvailableTime) {
mRunningStartTimeMillis = currentTime;
} else {
mEvents.addFirst(new HbmEvent(mRunningStartTimeMillis, currentTime));
@@ -161,30 +175,49 @@
return mHbmMode;
}
+ void stop() {
+ registerHdrListener(null /*displayToken*/);
+ }
+
+ void resetHbmData(IBinder displayToken, HighBrightnessModeData hbmData) {
+ mHbmData = hbmData;
+ unregisterHdrListener();
+ if (deviceSupportsHbm()) {
+ registerHdrListener(displayToken);
+ recalculateTimeAllowance();
+ }
+ }
+
void dump(PrintWriter pw) {
pw.println("HighBrightnessModeController:");
- pw.println(" mBrightnessMin=" + mBrightnessMin);
- pw.println(" mBrightnessMax=" + mBrightnessMax);
+ pw.println(" mCurrentMin=" + getCurrentBrightnessMin());
+ pw.println(" mCurrentMax=" + getCurrentBrightnessMax());
+ pw.println(" mHbmMode=" + BrightnessInfo.hbmToString(mHbmMode));
+ pw.println(" remainingTime=" + calculateRemainingTime(mClock.uptimeMillis()));
pw.println(" mHbmData=" + mHbmData);
pw.println(" mIsInAllowedAmbientRange=" + mIsInAllowedAmbientRange);
pw.println(" mIsTimeAvailable= " + mIsTimeAvailable);
pw.println(" mIsAutoBrightnessEnabled=" + mIsAutoBrightnessEnabled);
pw.println(" mAutoBrightness=" + mAutoBrightness);
+ pw.println(" mIsHdrLayerPresent=" + mIsHdrLayerPresent);
+ pw.println(" mBrightnessMin=" + mBrightnessMin);
+ pw.println(" mBrightnessMax=" + mBrightnessMax);
}
private boolean isCurrentlyAllowed() {
- return mIsAutoBrightnessEnabled && mIsTimeAvailable && mIsInAllowedAmbientRange;
+ return mIsHdrLayerPresent
+ || (mIsAutoBrightnessEnabled && mIsTimeAvailable && mIsInAllowedAmbientRange);
}
private boolean deviceSupportsHbm() {
return mHbmData != null;
}
- /**
- * Recalculates the allowable HBM time.
- */
- private void recalculateTimeAllowance() {
- final long currentTime = mClock.uptimeMillis();
+ private long calculateRemainingTime(long currentTime) {
+ if (!deviceSupportsHbm()) {
+ return 0;
+ }
+
long timeAlreadyUsed = 0;
// First, lets see how much time we've taken for any currently running
@@ -222,8 +255,15 @@
Slog.d(TAG, "Time already used after all sessions: " + timeAlreadyUsed);
}
- // See how much allowable time we have left.
- final long remainingTime = Math.max(0, mHbmData.timeMaxMillis - timeAlreadyUsed);
+ return Math.max(0, mHbmData.timeMaxMillis - timeAlreadyUsed);
+ }
+
+ /**
+ * Recalculates the allowable HBM time.
+ */
+ private void recalculateTimeAllowance() {
+ final long currentTime = mClock.uptimeMillis();
+ final long remainingTime = calculateRemainingTime(currentTime);
// We allow HBM if there is more than the minimum required time available
// or if brightness is already in the high range, if there is any time left at all.
@@ -242,6 +282,7 @@
// If we are not allowed...timeout when the oldest event moved outside of the timing
// window by at least minTime. Basically, we're calculating the soonest time we can
// get {@code timeMinMillis} back to us.
+ final long windowstartTimeMillis = currentTime - mHbmData.timeWindowMillis;
final HbmEvent lastEvent = mEvents.getLast();
final long startTimePlusMinMillis =
Math.max(windowstartTimeMillis, lastEvent.startTimeMillis)
@@ -278,12 +319,36 @@
}
private int calculateHighBrightnessMode() {
- if (deviceSupportsHbm() && isCurrentlyAllowed()) {
+ if (!deviceSupportsHbm()) {
+ return BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF;
+ } else if (mIsHdrLayerPresent) {
+ return BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR;
+ } else if (isCurrentlyAllowed()) {
return BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT;
}
+
return BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF;
}
+ private void registerHdrListener(IBinder displayToken) {
+ if (mRegisteredDisplayToken == displayToken) {
+ return;
+ }
+
+ unregisterHdrListener();
+ mRegisteredDisplayToken = displayToken;
+ if (mRegisteredDisplayToken != null) {
+ mHdrListener.register(mRegisteredDisplayToken);
+ }
+ }
+
+ private void unregisterHdrListener() {
+ if (mRegisteredDisplayToken != null) {
+ mHdrListener.unregister(mRegisteredDisplayToken);
+ mIsHdrLayerPresent = false;
+ }
+ }
+
/**
* Represents an event in which High Brightness Mode was enabled.
*/
@@ -302,4 +367,18 @@
+ ((endTimeMillis - startTimeMillis) / 1000) + "]";
}
}
+
+ private class HdrListener extends SurfaceControlHdrLayerInfoListener {
+ @Override
+ public void onHdrInfoChanged(IBinder displayToken, int numberOfHdrLayers,
+ int maxW, int maxH, int flags) {
+ mHandler.post(() -> {
+ mIsHdrLayerPresent = numberOfHdrLayers > 0;
+ // Calling the auto-brightness update so that we can recalculate
+ // auto-brightness with HDR in mind. When HDR layers are present,
+ // we don't limit auto-brightness' HBM time limits.
+ onAutoBrightnessChanged(mAutoBrightness);
+ });
+ }
+ }
}
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 2546118..754e35e 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -67,6 +67,8 @@
private static final int NO_DISPLAY_MODE_ID = 0;
+ private static final float NITS_INVALID = -1;
+
private final LongSparseArray<LocalDisplayDevice> mDevices = new LongSparseArray<>();
private final Injector mInjector;
@@ -190,6 +192,7 @@
private int mState = Display.STATE_UNKNOWN;
// This is only set in the runnable returned from requestDisplayStateLocked.
private float mBrightnessState = PowerManager.BRIGHTNESS_INVALID_FLOAT;
+ private float mSdrBrightnessState = PowerManager.BRIGHTNESS_INVALID_FLOAT;
private int mDefaultModeId;
private int mDefaultModeGroup;
private int mActiveModeId;
@@ -644,13 +647,15 @@
}
@Override
- public Runnable requestDisplayStateLocked(final int state, final float brightnessState) {
+ public Runnable requestDisplayStateLocked(final int state, final float brightnessState,
+ final float sdrBrightnessState) {
// Assume that the brightness is off if the display is being turned off.
assert state != Display.STATE_OFF || BrightnessSynchronizer.floatEquals(
brightnessState, PowerManager.BRIGHTNESS_OFF_FLOAT);
final boolean stateChanged = (mState != state);
- final boolean brightnessChanged = (!BrightnessSynchronizer.floatEquals(
- mBrightnessState, brightnessState));
+ final boolean brightnessChanged =
+ !(BrightnessSynchronizer.floatEquals(mBrightnessState, brightnessState)
+ && BrightnessSynchronizer.floatEquals(mSdrBrightnessState, sdrBrightnessState));
if (stateChanged || brightnessChanged) {
final long physicalDisplayId = mPhysicalDisplayId;
final IBinder token = getDisplayTokenLocked();
@@ -702,8 +707,9 @@
// Apply brightness changes given that we are in a non-suspended state.
if (brightnessChanged || vrModeChange) {
- setDisplayBrightness(brightnessState);
+ setDisplayBrightness(brightnessState, sdrBrightnessState);
mBrightnessState = brightnessState;
+ mSdrBrightnessState = sdrBrightnessState;
}
// Enter the final desired state, possibly suspended.
@@ -764,8 +770,8 @@
}
}
- private void setDisplayBrightness(float brightness) {
- // Ensure brightnessState is valid, before processing and sending to
+ private void setDisplayBrightness(float brightness, float sdrBrightness) {
+ // Ensure brightnessState is valid before processing and sending to
// surface control
if (Float.isNaN(brightness)) {
return;
@@ -774,17 +780,31 @@
if (DEBUG) {
Slog.d(TAG, "setDisplayBrightness("
+ "id=" + physicalDisplayId
- + ", brightness=" + brightness + ")");
+ + ", brightness=" + brightness
+ + ", sdrBrightness=" + sdrBrightness + ")");
}
Trace.traceBegin(Trace.TRACE_TAG_POWER, "setDisplayBrightness("
- + "id=" + physicalDisplayId + ", brightness=" + brightness + ")");
+ + "id=" + physicalDisplayId + ", brightness=" + brightness
+ + ", sdrBrightness=" + sdrBrightness + ")");
try {
- float backlight = brightnessToBacklight(brightness);
- mBacklightAdapter.setBacklight(backlight);
+ final float backlight = brightnessToBacklight(brightness);
+ float nits = NITS_INVALID;
+ float sdrBacklight = PowerManager.BRIGHTNESS_INVALID_FLOAT;
+ float sdrNits = NITS_INVALID;
+ if (getDisplayDeviceConfig().hasNitsMapping()
+ && sdrBrightness != PowerManager.BRIGHTNESS_INVALID_FLOAT) {
+ nits = backlightToNits(backlight);
+ sdrBacklight = brightnessToBacklight(sdrBrightness);
+ sdrNits = backlightToNits(sdrBacklight);
+ }
+ mBacklightAdapter.setBacklight(sdrBacklight, sdrNits, backlight, nits);
Trace.traceCounter(Trace.TRACE_TAG_POWER,
"ScreenBrightness",
BrightnessSynchronizer.brightnessFloatToInt(brightness));
+ Trace.traceCounter(Trace.TRACE_TAG_POWER,
+ "SdrScreenBrightness",
+ BrightnessSynchronizer.brightnessFloatToInt(sdrBrightness));
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
@@ -793,6 +813,10 @@
private float brightnessToBacklight(float brightness) {
return getDisplayDeviceConfig().getBacklightFromBrightness(brightness);
}
+
+ private float backlightToNits(float backlight) {
+ return getDisplayDeviceConfig().getNitsFromBacklight(backlight);
+ }
};
}
return null;
@@ -1242,6 +1266,13 @@
public boolean setDisplayBrightness(IBinder displayToken, float brightness) {
return SurfaceControl.setDisplayBrightness(displayToken, brightness);
}
+
+ public boolean setDisplayBrightness(IBinder displayToken, float sdrBacklight,
+ float sdrNits, float displayBacklight, float displayNits) {
+ return SurfaceControl.setDisplayBrightness(displayToken, sdrBacklight, sdrNits,
+ displayBacklight, displayNits);
+ }
+
}
static class BacklightAdapter {
@@ -1273,9 +1304,14 @@
}
// Set backlight within min and max backlight values
- void setBacklight(float backlight) {
+ void setBacklight(float sdrBacklight, float sdrNits, float backlight, float nits) {
if (mUseSurfaceControlBrightness || mForceSurfaceControl) {
- mSurfaceControlProxy.setDisplayBrightness(mDisplayToken, backlight);
+ if (sdrBacklight == PowerManager.BRIGHTNESS_INVALID_FLOAT) {
+ mSurfaceControlProxy.setDisplayBrightness(mDisplayToken, backlight);
+ } else {
+ mSurfaceControlProxy.setDisplayBrightness(mDisplayToken, sdrBacklight, sdrNits,
+ backlight, nits);
+ }
} else if (mBacklight != null) {
mBacklight.setBrightness(backlight);
}
diff --git a/services/core/java/com/android/server/display/RampAnimator.java b/services/core/java/com/android/server/display/RampAnimator.java
index 26004a8..20feafa 100644
--- a/services/core/java/com/android/server/display/RampAnimator.java
+++ b/services/core/java/com/android/server/display/RampAnimator.java
@@ -26,7 +26,7 @@
* A custom animator that progressively updates a property value at
* a given variable rate until it reaches a particular target value.
*/
-final class RampAnimator<T> {
+class RampAnimator<T> {
private final T mObject;
private final FloatProperty<T> mProperty;
private final Choreographer mChoreographer;
@@ -174,4 +174,52 @@
public interface Listener {
void onAnimationEnd();
}
+
+ static class DualRampAnimator<T> {
+ private final RampAnimator<T> mFirst;
+ private final RampAnimator<T> mSecond;
+ private final Listener mInternalListener = new Listener() {
+ @Override
+ public void onAnimationEnd() {
+ if (mListener != null && !isAnimating()) {
+ mListener.onAnimationEnd();
+ }
+ }
+ };
+
+ private Listener mListener;
+
+ DualRampAnimator(T object, FloatProperty<T> firstProperty,
+ FloatProperty<T> secondProperty) {
+ mFirst = new RampAnimator(object, firstProperty);
+ mFirst.setListener(mInternalListener);
+ mSecond = new RampAnimator(object, secondProperty);
+ mSecond.setListener(mInternalListener);
+ }
+
+ /**
+ * Starts animating towards the specified values.
+ *
+ * If this is the first time the property is being set or if the rate is 0,
+ * the value jumps directly to the target.
+ *
+ * @param firstTarget The first target value.
+ * @param secondTarget The second target value.
+ * @param rate The convergence rate in units per second, or 0 to set the value immediately.
+ * @return True if either target differs from the previous target.
+ */
+ public boolean animateTo(float firstTarget, float secondTarget, float rate) {
+ final boolean firstRetval = mFirst.animateTo(firstTarget, rate);
+ final boolean secondRetval = mSecond.animateTo(secondTarget, rate);
+ return firstRetval && secondRetval;
+ }
+
+ public void setListener(Listener listener) {
+ mListener = listener;
+ }
+
+ public boolean isAnimating() {
+ return mFirst.isAnimating() && mSecond.isAnimating();
+ }
+ }
}
diff --git a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
index 52a810b..b7931c8 100644
--- a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
@@ -293,7 +293,8 @@
}
@Override
- public Runnable requestDisplayStateLocked(int state, float brightnessState) {
+ public Runnable requestDisplayStateLocked(int state, float brightnessState,
+ float sdrBrightnessState) {
if (state != mDisplayState) {
mDisplayState = state;
if (state == Display.STATE_OFF) {
diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java
index f31d1da..0f6e384 100644
--- a/services/core/java/com/android/server/pm/ApexManager.java
+++ b/services/core/java/com/android/server/pm/ApexManager.java
@@ -25,6 +25,7 @@
import android.apex.ApexInfoList;
import android.apex.ApexSessionInfo;
import android.apex.ApexSessionParams;
+import android.apex.CompressedApexInfoList;
import android.apex.IApexService;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
@@ -374,6 +375,21 @@
public abstract void markBootCompleted();
/**
+ * Estimate how much storage space is needed on /data/ for decompressing apexes
+ * @param infoList List of apexes that are compressed in target build.
+ * @return Size, in bytes, the amount of space needed on /data/
+ */
+ public abstract long calculateSizeForCompressedApex(CompressedApexInfoList infoList)
+ throws RemoteException;
+
+ /**
+ * Reserve space on /data so that apexes can be decompressed after OTA
+ * @param infoList List of apexes that are compressed in target build.
+ */
+ public abstract void reserveSpaceForCompressedApex(CompressedApexInfoList infoList)
+ throws RemoteException;
+
+ /**
* Dumps various state information to the provided {@link PrintWriter} object.
*
* @param pw the {@link PrintWriter} object to send information to.
@@ -946,6 +962,18 @@
}
}
+ @Override
+ public long calculateSizeForCompressedApex(CompressedApexInfoList infoList)
+ throws RemoteException {
+ return waitForApexService().calculateSizeForCompressedApex(infoList);
+ }
+
+ @Override
+ public void reserveSpaceForCompressedApex(CompressedApexInfoList infoList)
+ throws RemoteException {
+ waitForApexService().reserveSpaceForCompressedApex(infoList);
+ }
+
/**
* Dump information about the packages contained in a particular cache
* @param packagesCache the cache to print information about.
@@ -1203,6 +1231,16 @@
}
@Override
+ public long calculateSizeForCompressedApex(CompressedApexInfoList infoList) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void reserveSpaceForCompressedApex(CompressedApexInfoList infoList) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
void dump(PrintWriter pw, String packageName) {
// No-op
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index bf114d8..a799ce2 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -3881,14 +3881,6 @@
@Override
public void onHealthStatus(int storageId, int status) {
if (mDestroyed || mDataLoaderFinished) {
- // App's installed.
- switch (status) {
- case IStorageHealthListener.HEALTH_STATUS_UNHEALTHY:
- if (systemDataLoader) {
- onSystemDataLoaderUnrecoverable();
- }
- return;
- }
return;
}
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 29496b3..3ee8b44 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -3021,7 +3021,7 @@
private int handleStartTransitionForKeyguardLw(boolean keyguardGoingAway, long duration) {
final int res = applyKeyguardOcclusionChange();
if (res != 0) return res;
- if (!WindowManagerService.sEnableRemoteKeyguardAnimation && keyguardGoingAway) {
+ if (!WindowManagerService.sEnableRemoteKeyguardGoingAwayAnimation && keyguardGoingAway) {
if (DEBUG_KEYGUARD) Slog.d(TAG, "Starting keyguard exit animation");
startKeyguardExitAnimation(SystemClock.uptimeMillis(), duration);
}
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
index 44f14b4..6e478ee7 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
@@ -263,7 +263,8 @@
*/
@Deprecated
public void setOccluded(boolean isOccluded, boolean animate) {
- if (!WindowManagerService.sEnableRemoteKeyguardAnimation && mKeyguardService != null) {
+ if (!WindowManagerService.sEnableRemoteKeyguardOccludeAnimation
+ && mKeyguardService != null) {
if (DEBUG) Log.v(TAG, "setOccluded(" + isOccluded + ") animate=" + animate);
mKeyguardService.setOccluded(isOccluded, animate);
}
@@ -403,7 +404,8 @@
}
public void startKeyguardExitAnimation(long startTime, long fadeoutDuration) {
- if (!WindowManagerService.sEnableRemoteKeyguardAnimation && mKeyguardService != null) {
+ if (!WindowManagerService.sEnableRemoteKeyguardGoingAwayAnimation
+ && mKeyguardService != null) {
mKeyguardService.startKeyguardExitAnimation(startTime, fadeoutDuration);
}
}
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 8052522..c4aca6c 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -102,6 +102,7 @@
import com.android.internal.app.IBatteryStats;
import com.android.internal.display.BrightnessSynchronizer;
import com.android.internal.os.BackgroundThread;
+import com.android.internal.util.ArrayUtils;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.Preconditions;
import com.android.server.EventLogTags;
@@ -2926,16 +2927,13 @@
private void scheduleSandmanLocked() {
if (!mSandmanScheduled) {
mSandmanScheduled = true;
- Message msg = mHandler.obtainMessage(MSG_SANDMAN);
- msg.setAsynchronous(true);
- mHandler.sendMessage(msg);
- }
- }
-
- private void handleSandman() {
- for (int id : mDisplayGroupPowerStateMapper.getDisplayGroupIdsLocked()) {
- if (mDisplayGroupPowerStateMapper.isSandmanSupported(id)) {
- handleSandman(id);
+ for (int id : mDisplayGroupPowerStateMapper.getDisplayGroupIdsLocked()) {
+ if (mDisplayGroupPowerStateMapper.isSandmanSupported(id)) {
+ Message msg = mHandler.obtainMessage(MSG_SANDMAN);
+ msg.arg1 = id;
+ msg.setAsynchronous(true);
+ mHandler.sendMessage(msg);
+ }
}
}
}
@@ -2953,6 +2951,11 @@
final int wakefulness;
synchronized (mLock) {
mSandmanScheduled = false;
+ final int[] ids = mDisplayGroupPowerStateMapper.getDisplayGroupIdsLocked();
+ if (!ArrayUtils.contains(ids, groupId)) {
+ // Group has been removed.
+ return;
+ }
// TODO (b/175764708): Support per-display doze.
wakefulness = getWakefulnessLocked();
if ((wakefulness == WAKEFULNESS_DREAMING || wakefulness == WAKEFULNESS_DOZING) &&
@@ -2986,6 +2989,12 @@
// Update dream state.
synchronized (mLock) {
+ final int[] ids = mDisplayGroupPowerStateMapper.getDisplayGroupIdsLocked();
+ if (!ArrayUtils.contains(ids, groupId)) {
+ // Group has been removed.
+ return;
+ }
+
// Remember the initial battery level when the dream started.
if (startDreaming && isDreaming) {
mBatteryLevelWhenDreamStarted = mBatteryLevel;
@@ -4770,7 +4779,7 @@
handleUserActivityTimeout();
break;
case MSG_SANDMAN:
- handleSandman();
+ handleSandman(msg.arg1);
break;
case MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT:
handleScreenBrightnessBoostTimeout();
diff --git a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewarePermission.java b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewarePermission.java
index d5ab574b..6f0741d 100644
--- a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewarePermission.java
+++ b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewarePermission.java
@@ -21,6 +21,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.AppOpsManager;
import android.content.Context;
import android.content.PermissionChecker;
import android.media.permission.Identity;
@@ -132,7 +133,12 @@
* Throws a {@link SecurityException} iff the originator has permission to receive data.
*/
void enforcePermissionsForDataDelivery(@NonNull Identity identity, @NonNull String reason) {
- enforcePermissionForDataDelivery(mContext, identity, RECORD_AUDIO, reason);
+ // START TEMP HACK
+ enforcePermissionForPreflight(mContext, identity, RECORD_AUDIO);
+ int hotwordOp = AppOpsManager.strOpToOp(AppOpsManager.OPSTR_RECORD_AUDIO_HOTWORD);
+ mContext.getSystemService(AppOpsManager.class).noteOpNoThrow(hotwordOp, identity.uid,
+ identity.packageName, identity.attributionTag, reason);
+ // END TEMP HACK
enforcePermissionForDataDelivery(mContext, identity, CAPTURE_AUDIO_HOTWORD,
reason);
}
diff --git a/services/core/java/com/android/server/wm/ActivityClientController.java b/services/core/java/com/android/server/wm/ActivityClientController.java
index efee0a1..eb9ab36 100644
--- a/services/core/java/com/android/server/wm/ActivityClientController.java
+++ b/services/core/java/com/android/server/wm/ActivityClientController.java
@@ -827,9 +827,9 @@
if (rootTask.inFreeformWindowingMode()) {
rootTask.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
- } else if (!mService.mSupportsNonResizableMultiWindow && r.inSizeCompatMode()) {
- throw new IllegalStateException("Size-compat windows are currently not"
- + "freeform-enabled");
+ } else if (!r.supportsFreeform()) {
+ throw new IllegalStateException(
+ "This activity is currently not freeform-enabled");
} else if (rootTask.getParent().inFreeformWindowingMode()) {
// If the window is on a freeform display, set it to undefined. It will be
// resolved to freeform and it can adjust windowing mode when the display mode
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 3e8bc5d..6957aa0 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -2465,8 +2465,7 @@
if (windowingMode == WINDOWING_MODE_PINNED && info.supportsPictureInPicture()) {
return false;
}
- if (WindowConfiguration.inMultiWindowMode(windowingMode)
- && mAtmService.mSupportsNonResizableMultiWindow
+ if (WindowConfiguration.inMultiWindowMode(windowingMode) && supportsMultiWindow()
&& !mAtmService.mForceResizableActivities) {
// The non resizable app will be letterboxed instead of being forced resizable.
return false;
diff --git a/services/core/java/com/android/server/wm/LaunchParamsPersister.java b/services/core/java/com/android/server/wm/LaunchParamsPersister.java
index 391e659..be3ceb8 100644
--- a/services/core/java/com/android/server/wm/LaunchParamsPersister.java
+++ b/services/core/java/com/android/server/wm/LaunchParamsPersister.java
@@ -232,6 +232,9 @@
void saveTask(Task task, DisplayContent display) {
final ComponentName name = task.realActivity;
+ if (name == null) {
+ return;
+ }
final int userId = task.mUserId;
PersistableLaunchParams params;
ArrayMap<ComponentName, PersistableLaunchParams> map = mLaunchParamsMap.get(userId);
@@ -381,11 +384,13 @@
private class PackageListObserver implements PackageManagerInternal.PackageListObserver {
@Override
- public void onPackageAdded(String packageName, int uid) { }
+ public void onPackageAdded(String packageName, int uid) {}
@Override
public void onPackageRemoved(String packageName, int uid) {
- removeRecordForPackage(packageName);
+ synchronized (mSupervisor.mService.getGlobalLock()) {
+ removeRecordForPackage(packageName);
+ }
}
}
diff --git a/services/core/java/com/android/server/wm/RootDisplayArea.java b/services/core/java/com/android/server/wm/RootDisplayArea.java
index cd20c82..1cda8d5 100644
--- a/services/core/java/com/android/server/wm/RootDisplayArea.java
+++ b/services/core/java/com/android/server/wm/RootDisplayArea.java
@@ -37,7 +37,7 @@
* of the whole logical display, or a {@link DisplayAreaGroup} as the root of a partition of the
* logical display.
*/
-class RootDisplayArea extends DisplayArea<DisplayArea> {
+class RootDisplayArea extends DisplayArea.Dimmable {
/** {@link Feature} that are supported in this {@link DisplayArea} hierarchy. */
List<DisplayAreaPolicyBuilder.Feature> mFeatures;
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 9fad7da..c6478ee 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -2836,14 +2836,13 @@
getResolvedOverrideConfiguration().windowConfiguration.setWindowingMode(windowingMode);
}
- // Do not allow non-resizable tasks to be in a multi-window mode, unless it is in pinned
- // windowing mode or supports non-resizable tasks in multi-window mode.
- if (!isResizeable()) {
+ // Do not allow tasks not support multi window to be in a multi-window mode, unless it is in
+ // pinned windowing mode.
+ if (!supportsMultiWindow()) {
final int candidateWindowingMode =
windowingMode != WINDOWING_MODE_UNDEFINED ? windowingMode : parentWindowingMode;
if (WindowConfiguration.inMultiWindowMode(candidateWindowingMode)
- && candidateWindowingMode != WINDOWING_MODE_PINNED
- && !mTaskSupervisor.mService.mSupportsNonResizableMultiWindow) {
+ && candidateWindowingMode != WINDOWING_MODE_PINNED) {
getResolvedOverrideConfiguration().windowConfiguration.setWindowingMode(
WINDOWING_MODE_FULLSCREEN);
}
@@ -7177,8 +7176,11 @@
if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare to back transition: task="
+ tr.mTaskId);
- mDisplayContent.prepareAppTransition(TRANSIT_TO_BACK);
- mDisplayContent.requestTransitionAndLegacyPrepare(TRANSIT_TO_BACK, tr);
+ // Skip the transition for pinned task.
+ if (!inPinnedWindowingMode()) {
+ mDisplayContent.prepareAppTransition(TRANSIT_TO_BACK);
+ mDisplayContent.requestTransitionAndLegacyPrepare(TRANSIT_TO_BACK, tr);
+ }
moveToBack("moveTaskToBackLocked", tr);
if (inPinnedWindowingMode()) {
diff --git a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
index 29677b2..0bc7999 100644
--- a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
+++ b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
@@ -612,7 +612,7 @@
private boolean shouldLaunchUnresizableAppInFreeform(ActivityRecord activity,
TaskDisplayArea displayArea) {
- if (!mSupervisor.mService.mSupportsNonResizableMultiWindow || activity.isResizeable()) {
+ if (!activity.supportsFreeform() || activity.isResizeable()) {
return false;
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 9e8b6a3..bd1d456 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -421,18 +421,41 @@
SystemProperties.getBoolean(DISABLE_CUSTOM_TASK_ANIMATION_PROPERTY, true);
/**
+ * Use WMShell for app transition.
+ */
+ public static final String ENABLE_SHELL_TRANSITIONS = "persist.debug.shell_transit";
+
+ /**
+ * @see #ENABLE_SHELL_TRANSITIONS
+ */
+ public static final boolean sEnableShellTransitions =
+ SystemProperties.getBoolean(ENABLE_SHELL_TRANSITIONS, false);
+
+ /**
* Run Keyguard animation as remote animation in System UI instead of local animation in
* the server process.
+ *
+ * 0: Runs all keyguard animation as local animation
+ * 1: Only runs keyguard going away animation as remote animation
+ * 2: Runs all keyguard animation as remote animation
*/
private static final String ENABLE_REMOTE_KEYGUARD_ANIMATION_PROPERTY =
"persist.wm.enable_remote_keyguard_animation";
+ private static final int sEnableRemoteKeyguardAnimation =
+ SystemProperties.getInt(ENABLE_REMOTE_KEYGUARD_ANIMATION_PROPERTY, 1);
+
/**
* @see #ENABLE_REMOTE_KEYGUARD_ANIMATION_PROPERTY
*/
- public static boolean sEnableRemoteKeyguardAnimation =
- SystemProperties.getBoolean(ENABLE_REMOTE_KEYGUARD_ANIMATION_PROPERTY, false);
+ public static final boolean sEnableRemoteKeyguardGoingAwayAnimation = !sEnableShellTransitions
+ && sEnableRemoteKeyguardAnimation >= 1;
+ /**
+ * @see #ENABLE_REMOTE_KEYGUARD_ANIMATION_PROPERTY
+ */
+ public static final boolean sEnableRemoteKeyguardOccludeAnimation = !sEnableShellTransitions
+ && sEnableRemoteKeyguardAnimation >= 2;
/**
* Allows a fullscreen windowing mode activity to launch in its desired orientation directly
@@ -8123,6 +8146,16 @@
return;
}
+ if (mRecentsAnimationController != null
+ && mRecentsAnimationController.getTargetAppMainWindow() == touchedWindow) {
+ // If there is an active recents animation and touched window is the target, then ignore
+ // the touch. The target already handles touches using its own input monitor and we
+ // don't want to trigger any lifecycle changes from focusing another window.
+ // TODO(b/186770026): We should remove this once we support multiple resumed activities
+ // while in overview
+ return;
+ }
+
ProtoLog.i(WM_DEBUG_FOCUS_LIGHT, "onPointerDownOutsideFocusLocked called on %s",
touchedWindow);
final DisplayContent displayContent = touchedWindow.getDisplayContent();
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 24f73c3..074eeb9 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -63,7 +63,7 @@
import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_HOME;
import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_NOTIFICATIONS;
import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW;
-import static android.app.admin.DevicePolicyManager.NEARBY_STREAMING_DISABLED;
+import static android.app.admin.DevicePolicyManager.NEARBY_STREAMING_NOT_CONTROLLED_BY_POLICY;
import static android.app.admin.DevicePolicyManager.NON_ORG_OWNED_PROFILE_KEYGUARD_FEATURES_AFFECT_OWNER;
import static android.app.admin.DevicePolicyManager.OPERATION_SAFETY_REASON_NONE;
import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_HIGH;
@@ -7548,21 +7548,25 @@
}
@Override
- public int getNearbyNotificationStreamingPolicy() {
+ public int getNearbyNotificationStreamingPolicy(final int userId) {
if (!mHasFeature) {
- return NEARBY_STREAMING_DISABLED;
+ return NEARBY_STREAMING_NOT_CONTROLLED_BY_POLICY;
}
final CallerIdentity caller = getCallerIdentity();
Preconditions.checkCallAuthorization(
- isDeviceOwner(caller)
- || isProfileOwner(caller)
- || hasCallingOrSelfPermission(permission.READ_NEARBY_STREAMING_POLICY));
+ isProfileOwner(caller)
+ || isDeviceOwner(caller)
+ || hasCallingOrSelfPermission(permission.READ_NEARBY_STREAMING_POLICY));
synchronized (getLockObject()) {
- final ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(caller);
- return admin.mNearbyNotificationStreamingPolicy;
+ if (mOwners.hasProfileOwner(userId) || mOwners.hasDeviceOwner()) {
+ final ActiveAdmin admin = getDeviceOrProfileOwnerAdminLocked(userId);
+ return admin.mNearbyNotificationStreamingPolicy;
+ }
}
+
+ return NEARBY_STREAMING_NOT_CONTROLLED_BY_POLICY;
}
@Override
@@ -7584,21 +7588,25 @@
}
@Override
- public int getNearbyAppStreamingPolicy() {
+ public int getNearbyAppStreamingPolicy(final int userId) {
if (!mHasFeature) {
- return NEARBY_STREAMING_DISABLED;
+ return NEARBY_STREAMING_NOT_CONTROLLED_BY_POLICY;
}
final CallerIdentity caller = getCallerIdentity();
Preconditions.checkCallAuthorization(
- isDeviceOwner(caller)
- || isProfileOwner(caller)
- || hasCallingOrSelfPermission(permission.READ_NEARBY_STREAMING_POLICY));
+ isProfileOwner(caller)
+ || isDeviceOwner(caller)
+ || hasCallingOrSelfPermission(permission.READ_NEARBY_STREAMING_POLICY));
synchronized (getLockObject()) {
- final ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(caller);
- return admin.mNearbyAppStreamingPolicy;
+ if (mOwners.hasProfileOwner(userId) || mOwners.hasDeviceOwner()) {
+ final ActiveAdmin admin = getDeviceOrProfileOwnerAdminLocked(userId);
+ return admin.mNearbyAppStreamingPolicy;
+ }
}
+
+ return NEARBY_STREAMING_NOT_CONTROLLED_BY_POLICY;
}
/**
diff --git a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java
index ed2e466..a2e813a 100644
--- a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java
@@ -62,7 +62,6 @@
import org.junit.After;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.quality.Strictness;
@@ -223,7 +222,6 @@
// Tests that ops are persisted during shutdown.
@Test
- @Ignore("b/183523911")
public void testShutdown() {
mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null, false, null, false);
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
index f1d8e6c..e1012a9 100644
--- a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
@@ -649,14 +649,14 @@
// Test as default display
BacklightAdapter ba = new BacklightAdapter(displayToken, true /*isDefault*/,
mSurfaceControlProxy);
- ba.setBacklight(0.514f);
- verify(mSurfaceControlProxy).setDisplayBrightness(displayToken, 0.514f);
+ ba.setBacklight(0.514f, 100f, 0.614f, 500f);
+ verify(mSurfaceControlProxy).setDisplayBrightness(displayToken, 0.514f, 100f, 0.614f, 500f);
// Test as not default display
BacklightAdapter ba2 = new BacklightAdapter(displayToken, false /*isDefault*/,
mSurfaceControlProxy);
- ba2.setBacklight(0.323f);
- verify(mSurfaceControlProxy).setDisplayBrightness(displayToken, 0.323f);
+ ba2.setBacklight(0.323f, 101f, 0.723f, 601f);
+ verify(mSurfaceControlProxy).setDisplayBrightness(displayToken, 0.323f, 101f, 0.723f, 601f);
}
@Test
@@ -668,7 +668,7 @@
BacklightAdapter ba = new BacklightAdapter(displayToken, true /*isDefault*/,
mSurfaceControlProxy);
- ba.setBacklight(0.123f);
+ ba.setBacklight(1f, 1f, 0.123f, 1f);
verify(mMockedBacklight).setBrightness(0.123f);
}
@@ -681,7 +681,7 @@
BacklightAdapter ba = new BacklightAdapter(displayToken, false /*isDefault*/,
mSurfaceControlProxy);
- ba.setBacklight(0.456f);
+ ba.setBacklight(0.456f, 1f, 1f, 1f);
// Adapter does not forward any brightness in this case.
verify(mMockedBacklight, never()).setBrightness(anyFloat());
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 5989bb6..2aad275 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
@@ -102,7 +102,7 @@
int nativeIndexRestorationCause =
InitializeStatsProto.RecoveryCause.INCONSISTENT_WITH_GROUND_TRUTH_VALUE;
int nativeSchemaStoreRecoveryCause =
- InitializeStatsProto.RecoveryCause.TOTAL_CHECKSUM_MISMATCH_VALUE;
+ InitializeStatsProto.RecoveryCause.SCHEMA_CHANGES_OUT_OF_SYNC_VALUE;
int nativeDocumentStoreRecoveryLatencyMillis = 7;
int nativeIndexRestorationLatencyMillis = 8;
int nativeSchemaStoreRecoveryLatencyMillis = 9;
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SnippetTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SnippetTest.java
index d0ce317..8fe1139 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SnippetTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SnippetTest.java
@@ -96,7 +96,7 @@
Collections.singletonList(DATABASE_NAME),
SCHEMA_MAP);
assertThat(searchResultPage.getResults()).hasSize(1);
- SearchResult.MatchInfo match = searchResultPage.getResults().get(0).getMatches().get(0);
+ SearchResult.MatchInfo match = searchResultPage.getResults().get(0).getMatchInfos().get(0);
assertThat(match.getPropertyPath()).isEqualTo(propertyKeyString);
assertThat(match.getFullText()).isEqualTo(propertyValueString);
assertThat(match.getExactMatch()).isEqualTo(exactMatch);
@@ -142,7 +142,7 @@
Collections.singletonList(DATABASE_NAME),
SCHEMA_MAP);
assertThat(searchResultPage.getResults()).hasSize(1);
- assertThat(searchResultPage.getResults().get(0).getMatches()).isEmpty();
+ assertThat(searchResultPage.getResults().get(0).getMatchInfos()).isEmpty();
}
@Test
@@ -198,7 +198,7 @@
Collections.singletonList(DATABASE_NAME),
SCHEMA_MAP);
assertThat(searchResultPage.getResults()).hasSize(1);
- SearchResult.MatchInfo match1 = searchResultPage.getResults().get(0).getMatches().get(0);
+ SearchResult.MatchInfo match1 = searchResultPage.getResults().get(0).getMatchInfos().get(0);
assertThat(match1.getPropertyPath()).isEqualTo("senderName");
assertThat(match1.getFullText()).isEqualTo("Test Name Jr.");
assertThat(match1.getExactMatchRange())
@@ -208,7 +208,7 @@
.isEqualTo(new SearchResult.MatchRange(/*lower=*/ 0, /*upper=*/ 9));
assertThat(match1.getSnippet()).isEqualTo("Test Name");
- SearchResult.MatchInfo match2 = searchResultPage.getResults().get(0).getMatches().get(1);
+ SearchResult.MatchInfo match2 = searchResultPage.getResults().get(0).getMatchInfos().get(1);
assertThat(match2.getPropertyPath()).isEqualTo("senderEmail");
assertThat(match2.getFullText()).isEqualTo("TestNameJr@gmail.com");
assertThat(match2.getExactMatchRange())
@@ -281,7 +281,7 @@
Collections.singletonList(DATABASE_NAME),
SCHEMA_MAP);
assertThat(searchResultPage.getResults()).hasSize(1);
- SearchResult.MatchInfo match1 = searchResultPage.getResults().get(0).getMatches().get(0);
+ SearchResult.MatchInfo match1 = searchResultPage.getResults().get(0).getMatchInfos().get(0);
assertThat(match1.getPropertyPath()).isEqualTo("sender.name");
assertThat(match1.getFullText()).isEqualTo("Test Name Jr.");
assertThat(match1.getExactMatchRange())
@@ -291,7 +291,7 @@
.isEqualTo(new SearchResult.MatchRange(/*lower=*/ 0, /*upper=*/ 9));
assertThat(match1.getSnippet()).isEqualTo("Test Name");
- SearchResult.MatchInfo match2 = searchResultPage.getResults().get(0).getMatches().get(1);
+ SearchResult.MatchInfo match2 = searchResultPage.getResults().get(0).getMatchInfos().get(1);
assertThat(match2.getPropertyPath()).isEqualTo("sender.email[1]");
assertThat(match2.getFullText()).isEqualTo("TestNameJr2@gmail.com");
assertThat(match2.getExactMatchRange())
diff --git a/services/tests/servicestests/src/com/android/server/display/HighBrightnessModeControllerTest.java b/services/tests/servicestests/src/com/android/server/display/HighBrightnessModeControllerTest.java
index 88a21b4..8e4cdc9 100644
--- a/services/tests/servicestests/src/com/android/server/display/HighBrightnessModeControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/HighBrightnessModeControllerTest.java
@@ -21,6 +21,7 @@
import static org.junit.Assert.assertEquals;
+import android.os.Binder;
import android.os.Handler;
import android.os.Message;
import android.os.test.TestLooper;
@@ -55,6 +56,7 @@
private OffsettableClock mClock;
private TestLooper mTestLooper;
private Handler mHandler;
+ private Binder mDisplayToken;
private static final HighBrightnessModeData DEFAULT_HBM_DATA =
new HighBrightnessModeData(MINIMUM_LUX, TRANSITION_POINT, TIME_WINDOW_MILLIS,
@@ -64,6 +66,7 @@
public void setUp() {
mClock = new OffsettableClock.Stopped();
mTestLooper = new TestLooper(mClock::now);
+ mDisplayToken = null;
mHandler = new Handler(mTestLooper.getLooper(), new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
@@ -79,14 +82,14 @@
@Test
public void testNoHbmData() {
final HighBrightnessModeController hbmc = new HighBrightnessModeController(
- mClock::now, mHandler, DEFAULT_MIN, DEFAULT_MAX, null, () -> {});
+ mClock::now, mHandler, mDisplayToken, DEFAULT_MIN, DEFAULT_MAX, null, () -> {});
assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_OFF);
}
@Test
public void testNoHbmData_Enabled() {
final HighBrightnessModeController hbmc = new HighBrightnessModeController(
- mClock::now, mHandler, DEFAULT_MIN, DEFAULT_MAX, null, () -> {});
+ mClock::now, mHandler, mDisplayToken, DEFAULT_MIN, DEFAULT_MAX, null, () -> {});
hbmc.setAutoBrightnessEnabled(true);
hbmc.onAmbientLuxChange(MINIMUM_LUX - 1); // below allowed range
assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_OFF);
@@ -264,8 +267,8 @@
// Creates instance with standard initialization values.
private HighBrightnessModeController createDefaultHbm() {
- return new HighBrightnessModeController(mClock::now, mHandler, DEFAULT_MIN, DEFAULT_MAX,
- DEFAULT_HBM_DATA, () -> {});
+ return new HighBrightnessModeController(mClock::now, mHandler, mDisplayToken, DEFAULT_MIN,
+ DEFAULT_MAX, DEFAULT_HBM_DATA, () -> {});
}
private void advanceTime(long timeMs) {
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 b1582be..765c13a 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
@@ -963,7 +963,7 @@
parser.setInput(is, "UTF-8");
parser.nextTag();
- FontConfig.FontFamily fontFamily = FontListParser.readFamily(parser, "", null);
+ FontConfig.FontFamily fontFamily = FontListParser.readFamily(parser, "", null, true);
List<FontUpdateRequest.Font> fonts = new ArrayList<>();
for (FontConfig.Font font : fontFamily.getFontList()) {
String name = font.getFile().getName();
diff --git a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
index b7d8638..7cb7c79d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
@@ -114,10 +114,10 @@
when(mRootWindowContainer.getDisplayContent(eq(mDisplayUniqueId)))
.thenReturn(mTestDisplay);
- Task stack = mTestDisplay.getDefaultTaskDisplayArea()
+ Task rootTask = mTestDisplay.getDefaultTaskDisplayArea()
.createRootTask(TEST_WINDOWING_MODE, ACTIVITY_TYPE_STANDARD, /* onTop */ true);
- mTestTask = new TaskBuilder(mSupervisor).setComponent(TEST_COMPONENT).setParentTask(stack)
- .build();
+ mTestTask = new TaskBuilder(mSupervisor).setComponent(TEST_COMPONENT)
+ .setParentTask(rootTask).build();
mTestTask.mUserId = TEST_USER_ID;
mTestTask.mLastNonFullscreenBounds = TEST_BOUNDS;
mTestTask.setHasBeenVisible(true);
@@ -158,6 +158,17 @@
}
@Test
+ public void testSavingTestWithoutRealActivityWontMakePackageRemovalCrash() {
+ Task rootTask = mTestDisplay.getDefaultTaskDisplayArea()
+ .createRootTask(TEST_WINDOWING_MODE, ACTIVITY_TYPE_STANDARD, /* onTop */ true);
+ assertNull(rootTask.realActivity);
+
+ mTarget.saveTask(rootTask);
+
+ mTarget.removeRecordForPackage(TEST_COMPONENT.getPackageName());
+ }
+
+ @Test
public void testSavesAndRestoresLaunchParamsInSameInstance() {
mTarget.saveTask(mTestTask);
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 2389d2d..13ef998 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
@@ -80,6 +80,7 @@
import android.util.TypedXmlPullParser;
import android.util.TypedXmlSerializer;
import android.util.Xml;
+import android.view.Display;
import android.view.DisplayInfo;
import androidx.test.filters.MediumTest;
@@ -1338,6 +1339,16 @@
verify(display).onDescendantOrientationChanged(same(task));
}
+ @Test
+ public void testGetNonNullDimmerOnUntrustedDisplays() {
+ final DisplayInfo untrustedDisplayInfo = new DisplayInfo(mDisplayInfo);
+ untrustedDisplayInfo.flags &= ~Display.FLAG_TRUSTED;
+ final DisplayContent untrustedDisplay = createNewDisplay(untrustedDisplayInfo);
+ final ActivityRecord activity = createActivityRecord(untrustedDisplay);
+ activity.setOccludesParent(false);
+ assertNotNull(activity.getTask().getDimmer());
+ }
+
private Task getTestTask() {
final Task task = new TaskBuilder(mSupervisor).setCreateActivity(true).build();
return task.getBottomMostTask();
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index f7e6375..128602d 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -943,16 +943,7 @@
.APP_USAGE_EVENT_OCCURRED__EVENT_TYPE__MOVE_TO_FOREGROUND);
// check if this activity has already been resumed
if (mVisibleActivities.get(event.mInstanceId) != null) break;
- final String usageSourcePackage;
- switch(mUsageSource) {
- case USAGE_SOURCE_CURRENT_ACTIVITY:
- usageSourcePackage = event.mPackage;
- break;
- case USAGE_SOURCE_TASK_ROOT_ACTIVITY:
- default:
- usageSourcePackage = event.mTaskRootPackage;
- break;
- }
+ final String usageSourcePackage = getUsageSourcePackage(event);
try {
mAppTimeLimit.noteUsageStart(usageSourcePackage, userId);
} catch (IllegalArgumentException iae) {
@@ -964,26 +955,34 @@
mVisibleActivities.put(event.mInstanceId, resumedData);
break;
case Event.ACTIVITY_PAUSED:
- final ActivityData pausedData = mVisibleActivities.get(event.mInstanceId);
+ ActivityData pausedData = mVisibleActivities.get(event.mInstanceId);
if (pausedData == null) {
- Slog.w(TAG, "Unexpected activity event reported! (" + event.mPackage
- + "/" + event.mClass + " event : " + event.mEventType
- + " instanceId : " + event.mInstanceId + ")");
- } else {
- pausedData.lastEvent = Event.ACTIVITY_PAUSED;
- if (event.mTaskRootPackage == null) {
- // Task Root info is missing. Repair the event based on previous data
- event.mTaskRootPackage = pausedData.mTaskRootPackage;
- event.mTaskRootClass = pausedData.mTaskRootClass;
+ // Must have transitioned from Stopped/Destroyed to Paused state.
+ final String usageSourcePackage2 = getUsageSourcePackage(event);
+ try {
+ mAppTimeLimit.noteUsageStart(usageSourcePackage2, userId);
+ } catch (IllegalArgumentException iae) {
+ Slog.e(TAG, "Failed to note usage start", iae);
}
+ pausedData = new ActivityData(event.mTaskRootPackage, event.mTaskRootClass,
+ usageSourcePackage2);
+ mVisibleActivities.put(event.mInstanceId, pausedData);
+ } else {
+ FrameworkStatsLog.write(
+ FrameworkStatsLog.APP_USAGE_EVENT_OCCURRED,
+ uid,
+ event.mPackage,
+ event.mClass,
+ FrameworkStatsLog
+ .APP_USAGE_EVENT_OCCURRED__EVENT_TYPE__MOVE_TO_BACKGROUND);
}
- FrameworkStatsLog.write(
- FrameworkStatsLog.APP_USAGE_EVENT_OCCURRED,
- uid,
- event.mPackage,
- event.mClass,
- FrameworkStatsLog
- .APP_USAGE_EVENT_OCCURRED__EVENT_TYPE__MOVE_TO_BACKGROUND);
+
+ pausedData.lastEvent = Event.ACTIVITY_PAUSED;
+ if (event.mTaskRootPackage == null) {
+ // Task Root info is missing. Repair the event based on previous data
+ event.mTaskRootPackage = pausedData.mTaskRootPackage;
+ event.mTaskRootClass = pausedData.mTaskRootClass;
+ }
break;
case Event.ACTIVITY_DESTROYED:
// Treat activity destroys like activity stops.
@@ -993,7 +992,9 @@
final ActivityData prevData =
mVisibleActivities.removeReturnOld(event.mInstanceId);
if (prevData == null) {
- // The activity stop was already handled.
+ Slog.w(TAG, "Unexpected activity event reported! (" + event.mPackage
+ + "/" + event.mClass + " event : " + event.mEventType
+ + " instanceId : " + event.mInstanceId + ")");
return;
}
@@ -1059,6 +1060,16 @@
}
}
+ private String getUsageSourcePackage(Event event) {
+ switch(mUsageSource) {
+ case USAGE_SOURCE_CURRENT_ACTIVITY:
+ return event.mPackage;
+ case USAGE_SOURCE_TASK_ROOT_ACTIVITY:
+ default:
+ return event.mTaskRootPackage;
+ }
+ }
+
/**
* Some events like FLUSH_TO_DISK need to be sent to all userId.
* @param event
diff --git a/services/usb/java/com/android/server/usb/UsbService.java b/services/usb/java/com/android/server/usb/UsbService.java
index ac6b8fe..3d3538d 100644
--- a/services/usb/java/com/android/server/usb/UsbService.java
+++ b/services/usb/java/com/android/server/usb/UsbService.java
@@ -200,7 +200,7 @@
final IntentFilter filter = new IntentFilter();
filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
- mContext.registerReceiver(receiver, filter, null, null);
+ mContext.registerReceiverAsUser(receiver, UserHandle.ALL, filter, null, null);
}
/**
diff --git a/telecomm/java/android/telecom/DiagnosticCall.java b/telecomm/java/android/telecom/DiagnosticCall.java
deleted file mode 100644
index a6b7258..0000000
--- a/telecomm/java/android/telecom/DiagnosticCall.java
+++ /dev/null
@@ -1,27 +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 android.telecom;
-
-import android.annotation.SystemApi;
-
-/**
- * @deprecated use {@link CallDiagnostics} instead.
- * @hide
- */
-@SystemApi
-public abstract class DiagnosticCall extends CallDiagnostics {
-}
diff --git a/telecomm/java/android/telecom/Logging/Session.java b/telecomm/java/android/telecom/Logging/Session.java
index 4aa3614..e2fb601 100644
--- a/telecomm/java/android/telecom/Logging/Session.java
+++ b/telecomm/java/android/telecom/Logging/Session.java
@@ -453,19 +453,19 @@
@Override
public String toString() {
- if (mParentSession != null && mIsStartedFromActiveSession) {
+ Session sessionToPrint = this;
+ if (getParentSession() != null && isStartedFromActiveSession()) {
// Log.startSession was called from within another active session. Use the parent's
// Id instead of the child to reduce confusion.
- return mParentSession.toString();
- } else {
- StringBuilder methodName = new StringBuilder();
- methodName.append(getFullMethodPath(false /*truncatePath*/));
- if (mOwnerInfo != null && !mOwnerInfo.isEmpty()) {
- methodName.append("(");
- methodName.append(mOwnerInfo);
- methodName.append(")");
- }
- return methodName.toString() + "@" + getFullSessionId();
+ sessionToPrint = getRootSession("toString");
}
+ StringBuilder methodName = new StringBuilder();
+ methodName.append(sessionToPrint.getFullMethodPath(false /*truncatePath*/));
+ if (sessionToPrint.getOwnerInfo() != null && !sessionToPrint.getOwnerInfo().isEmpty()) {
+ methodName.append("(");
+ methodName.append(sessionToPrint.getOwnerInfo());
+ methodName.append(")");
+ }
+ return methodName.toString() + "@" + sessionToPrint.getFullSessionId();
}
}
diff --git a/telephony/java/android/telephony/CellIdentityNr.java b/telephony/java/android/telephony/CellIdentityNr.java
index cdd54cd..4f50521 100644
--- a/telephony/java/android/telephony/CellIdentityNr.java
+++ b/telephony/java/android/telephony/CellIdentityNr.java
@@ -233,7 +233,7 @@
}
/**
- * @return Mobile Network Code in string fomrat, or {@code null} if unknown.
+ * @return Mobile Network Code in string format, or {@code null} if unknown.
*/
@Nullable
public String getMncString() {
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 179aead..05f5d29 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -15036,15 +15036,6 @@
"CAPABILITY_SLICING_CONFIG_SUPPORTED";
/**
- * Indicates whether PHYSICAL_CHANNEL_CONFIG HAL1.6 is supported. See comments on
- * respective methods for more information.
- *
- * @hide
- */
- public static final String CAPABILITY_PHYSICAL_CHANNEL_CONFIG_1_6_SUPPORTED =
- "CAPABILITY_PHYSICAL_CHANNEL_CONFIG_1_6_SUPPORTED";
-
- /**
* A list of the radio interface capability values with public valid constants.
*
* Here is a related list for the systemapi-only valid constants:
diff --git a/telephony/java/android/telephony/ims/SipDelegateImsConfiguration.java b/telephony/java/android/telephony/ims/SipDelegateImsConfiguration.java
index ffbfde6..08513c2 100644
--- a/telephony/java/android/telephony/ims/SipDelegateImsConfiguration.java
+++ b/telephony/java/android/telephony/ims/SipDelegateImsConfiguration.java
@@ -26,6 +26,7 @@
import android.os.Parcel;
import android.os.Parcelable;
import android.os.PersistableBundle;
+import android.text.TextUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -561,7 +562,12 @@
builder.setSipCniHeader(getString(KEY_SIP_CONFIG_CELLULAR_NETWORK_INFO_HEADER_STRING));
builder.setSipAssociatedUriHeader(getString(KEY_SIP_CONFIG_P_ASSOCIATED_URI_HEADER_STRING));
if (getBoolean(KEY_SIP_CONFIG_IS_GRUU_ENABLED_BOOL, false)) {
- builder.setPublicGruuUri(Uri.parse(getString(KEY_SIP_CONFIG_UE_PUBLIC_GRUU_STRING)));
+ String uri = getString(KEY_SIP_CONFIG_UE_PUBLIC_GRUU_STRING);
+ Uri gruuUri = null;
+ if (!TextUtils.isEmpty(uri)) {
+ gruuUri = Uri.parse(uri);
+ }
+ builder.setPublicGruuUri(gruuUri);
}
if (getBoolean(KEY_SIP_CONFIG_IS_IPSEC_ENABLED_BOOL, false)) {
builder.setIpSecConfiguration(new SipDelegateConfiguration.IpSecConfiguration(